首页 > 试题广场 >

围棋遍历

[编程题]围棋遍历
  • 热度指数:1276 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
函数calc计算围棋中位置(x,y)处连成一片的棋子个数。所谓连成一片,即沿着棋盘横竖线往任意方向遍历,遍历过程允许转弯,不允许走斜线,中间未出现对方棋子或空子。

enum color {
    NONE, WHITE, BLACK,         // 棋子颜色,NONE表示未落子
};
struct weiqi {
    enum color board[19][19];   // 棋盘上每个位置的落子
};
int calc(struct weiqi *wq, int x, int y)
{
}


输入描述:
第1-19行数据是棋盘上棋子的颜色数据。0表示未落子,1表示白子,2表示黑子。 第1行最左边位置的坐标是(0,0),第1行第2列的坐标是(1,0),第2行第1列的坐标是(0,1),依此类推。 第20行数据是起始坐标(x,y)


输出描述:
与坐标(X,Y)连成一片的棋子数目
示例1

输入

0000000000000000000
0000011000000000000
0000001111000000000
0000001021000000000
0000001010100000000
0000000000000000000
0000000000000000000
0000000000000000000
0000000000000000000
0000000000000000000
0000000000000000000
0000000000000000000
0000000000000000000
0000000000000000000
0000000000000000000
0000000000000000000
0000000000000000000
0000000000000000000
0000000000000000000
5,1

输出

9
因为用例给出的点有可能是NONE、WHILE、BLACK,这时候可以在calc函数外面再套一层函数,用来获取点的值,把这个值作为标准传进递归里面,找出剩下的点。
int real_calc(struct weiqi *wq, int x, int y,enum color a)
{
    static int dir[][2]={{1,0},{0,1},{-1,0},{0,-1}};
    int num=0;
    if(wq->board[y][x] == a){
        ++num;
        wq->board[y][x] = NONE;
        for(int i=0;i<4;++i){
            num+=real_calc(wq, x+dir[i][0], y+dir[i][1],a);
        }
    }
    return num;
}
int calc(struct weiqi *wq, int x, int y)
{
    enum color a=wq->board[y][x];
    if (a==NONE)return 0;
    int num=real_calc(wq,x,y,a);
    return num;
}


发表于 2020-11-17 22:33:24 回复(0)
破坏性递归,回溯复原就超时了
int calc(struct weiqi* wq, int x, int y)
{
    static int dir[][2] = { {1,0},{0,1},{0,-1},{-1,0} };
    static color current = wq->board[y][x];
    if (x >= 19
        || x < 0
        || y >= 19
        || y < 0
        || wq->board[y][x] != current
        || wq->board[y][x] == NONE
        )
        return 0;
    int counter = 1;
    wq->board[y][x] = NONE;
    for (int i = 0; i< 4; i++)
        counter+=calc(wq, x + dir[i][0], y + dir[i][1]);
    return counter;
}


发表于 2020-06-05 19:04:24 回复(0)
import java.util.*;

public class Main{
    public static void main(String args[]){
        Scanner in = new Scanner(System.in);
        int[][] grid = new int[19][19];
        for(int i=0; i<19; i++){
            String str = in.nextLine();
            char[] line = str.toCharArray();
            for(int j=0; j<19; j++){
                grid[i][j] = Integer.parseInt(String.valueOf(line[j]));
            }
        }
        String str2 = in.nextLine();
        String[] arr = str2.split(",");
        int y = Integer.parseInt(arr[0]);
        int x = Integer.parseInt(arr[1]);

        int flag = grid[x][y];
        int res = 0;
        res = dfs(grid, x, y, flag);
        System.out.print(res);
    }
    
    private static int dfs(int[][] grid, int x, int y, int flag){
        if(x<0 || y<0 || x>=19 || y>=19){
            return 0;
        }
        
        if(grid[x][y] == 0 || grid[x][y] != flag){
            return 0;
        }
        
        int num = 0;
        
        if(grid[x][y] == flag){
            num = num+1;
            grid[x][y] = 0;
            num += dfs(grid, x-1, y, flag) 
             + dfs(grid, x+1, y, flag)
             + dfs(grid, x, y-1, flag)
             + dfs(grid, x, y+1, flag);
        }
        
        return num;
    }
}
发表于 2022-07-07 11:24:11 回复(0)
int dfsW(struct weiqi *wq,int y,int x){
    
    if(x<0||x>19||y<0||y>19) return 0;
    if(wq->board[y][x]!=WHITE) return 0;
    wq->board[y][x]=NONE;
        
    return 1+dfsW(wq,y-1,x)+dfsW(wq,y+1,x)+dfsW(wq,y,x-1)+dfsW(wq,y,x+1);
        
    
}

int dfsB(struct weiqi *wq,int y,int x){
    
    if(x<0||x>19||y<0||y>19) return 0;
    if(wq->board[y][x]!=BLACK) return 0;
    wq->board[y][x]=NONE;
        
    return 1+dfsB(wq,y-1,x)+dfsB(wq,y+1,x)+dfsB(wq,y,x-1)+dfsB(wq,y,x+1);
        
    
}

int calc(struct weiqi *wq, int x, int y)
{
    if(wq->board[y][x]==NONE) return 0;
    return wq->board[y][x]==WHITE?dfsW(wq,y,x):dfsB(wq,y,x);   
    
}

发表于 2021-03-06 14:36:45 回复(0)
利用队列存储相邻 同值的棋盘位置,存储一个后则将原位置值改为none,每次入队就计数,最后返回计数值
int calc(struct weiqi *wq, int x, int y)
{
	//TODO:
	color value = wq->board[y][x];
	if (value == NONE) return 0;

	dot pos, out;
	int count = 1;
	pos.x = x;
	pos.y = y;
	wq->board[pos.y][pos.x] = NONE;
	queue<dot> st;
	st.push(pos);
	while (!st.empty()) {
		out = st.front();
		st.pop();
		if (out.y - 1 >= 0 && wq->board[out.y - 1][out.x] == value) {
			count++;
			pos.x = out.x;
			pos.y = out.y - 1;
			st.push(pos);
			wq->board[pos.y][pos.x] = NONE;
		}
		if (out.x + 1 < 19 && wq->board[out.y][out.x + 1] == value) {
			count++;
			pos.x = out.x + 1;
			pos.y = out.y;
			st.push(pos);
			wq->board[pos.y][pos.x] = NONE;
		}
		if (out.y + 1 < 19 && wq->board[out.y + 1][out.x] == value) {
			count++;
			pos.x = out.x;
			pos.y = out.y + 1;
			st.push(pos);
			wq->board[pos.y][pos.x] = NONE;
		}
		if (out.x - 1 >= 0 && wq->board[out.y][out.x - 1] == value) {
			count++;
			pos.x = out.x - 1;
			pos.y = out.y;
			st.push(pos);
			wq->board[pos.y][pos.x] = NONE;
		}
	}
	return count;
}

编辑于 2020-05-23 20:10:22 回复(0)
#include <stdio.h>
#include <string.h>

enum color {
    NONE, WHITE, BLACK,         //棋子颜色,NONE表示未落子
};
struct weiqi {
    enum color board[19][19];   //棋盘上每个位置的落子
};

int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
bool flag[19][19];

void dfs(struct weiqi *wq, int x, int y, color c, int &ans) {

    if (flag[y][x]) return;

    color cr = wq->board[y][x];
    if (cr == c) {
        ans++;
        flag[y][x] = true;
    }

    for (int i = 0; i < 4; i++) {
        int nx = x + dx[i];
        int ny = y + dy[i];
        if (nx >= 0 && nx < 19 && ny >= 0 && ny < 19) {
            if (wq->board[ny][nx] == c && !flag[ny][nx])
                dfs(wq, nx, ny, c, ans);
        }
    }
}

int calc(struct weiqi *wq, int x, int y)
{
    //TODO:
    color c = wq->board[y][x];
    int ans = 0;
    if (c == NONE) return 0;
    dfs(wq, x, y, c, ans);
    return ans;
}
int input(struct weiqi *wq, int *x, int *y)
{
    int row, col;
    int ret;
    char buf[80];
    
    for (row = 0; row < 19; ++row) {
        if (fgets(buf, sizeof(buf), stdin) == NULL)
            return -1;
        if (strlen(buf) < 19)
            return -1;
        for (col = 0; col < 19; ++col) {
            switch (buf[col]) {
            case '0':
                wq->board[row][col] = NONE;
                break;
            case '1':
                wq->board[row][col] = WHITE;
                break;
            case '2':
                wq->board[row][col] = BLACK;
                break;
            default:
                return -1;
            }
        }
    }
    ret = fscanf(stdin, "%d,%d\n", x, y);
    if (ret != 2)
        return -1;
    for (row = 0 ; row < 19; ++row) {
        for (col = 0; col < 19; ++col) {
            fprintf(stderr, "%d ", wq->board[row][col]);
        }
        fprintf(stderr, "\n");
    }
    fprintf(stderr, "x = %d, y = %d\n", *x, *y);
    return 0;
}

int main()
{
    struct weiqi wq;
    int x = 0, y = 0;
    int cnt;

    memset(&wq, 0, sizeof(wq));
    if (input(&wq, &x, &y) < 0) {
        fprintf(stderr, "error!\n");
        return 1;
    }
    cnt = calc(&wq, x, y);

    printf("%d\n", cnt);
    return 0;
}
递归做法,不需要回溯,只需要判断下一个棋子是否符合条件
发表于 2024-08-19 10:59:37 回复(0)
这题应该考的是并查集,用递归直接超时
发表于 2023-09-06 17:19:18 回复(0)