题意:就是找每一个*区域中有多少个X区域,相连的条件是有公共边,公共点不算
分析:用两次dfs,dfs1用来搜索*区域,并把每一个*变为 . , 在这个过程中如果碰到X,则执行dfs2,用来搜索与该X相连的其他X,并且把X变为*
这道题有一个细节就是,在dfs1中,必须先搜索X,在搜索*,看这样一个例子:
6 6
......
..*X..
..*...
......
......
......
如果先搜索X,答案是1,正确;如果先搜索*,答案是0 1,错误
因为在搜索X时,搜索结束后,要搜索的坐标值仍是X的坐标值,此时X变为*,这时候正好继续搜索*,但是如果先搜索*在搜索X,那么X搜索结束后,会进行下一轮循环,此时要搜索的坐标值发生改变,那么刚刚那个由X变来的*就会被我们忽略过去了,比如像例子这种对角的情况。
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<cmath> using namespace std; char map[52][52]; int r[52]; int w, h; int sum; int M_num; void dfs1(int i, int j); void dfs2(int i, int j); void dfs1(int x, int y) { printf("dfs1:%d %d\n", x, y); map[x][y] = '.'; for (int i = -1; i <= 1; i++) for (int j = -1; j <=1; j++) { if ((i == -1 && j == 1) || (i == 1 && j == -1) || (i == 1 && j == 1) || (i == -1 && j == -1)) continue; int x0 = x + i; int y0 = y + j; if (x0 >= 0 && x0 < h && y0 >= 0 && y0 < w){ if (map[x0][y0] == 'X') { //这里要先搜索X dfs2(x0, y0); M_num++; } if (map[x0][y0] == '*'){ dfs1(x0, y0); } } } } void dfs2(int i, int j){ printf("dfs2:%d %d\n", i, j); map[i][j] = '*'; for(int p = -1; p<=1; p++){ for(int q = -1; q<=1; q++){ if(p == 1 && q == 1 || p == -1 && q == -1 || p == 1 && q == -1 || p == -1 && q == 1) continue; int nx = i+p, ny =j+q; if(nx>=0 && nx<h && ny>=0 && ny<w && map[nx][ny] == 'X'){ dfs2(nx, ny); } } } } int main(){ int T = 1; while(scanf("%d %d", &w, &h) == 2 && w){ memset(r, 0, sizeof(r)); memset(map, 0, sizeof(map)); sum = 0; for(int i = 0; i<h; i++){ scanf("%s", map[i]); } for(int i = 0; i<h; i++){ for(int j = 0; j<w; j++){ if(map[i][j] == '*') { M_num = 0; dfs1(i, j); r[sum] = M_num; sum ++; printf("cut!\n"); } } } sort(r, r+sum); printf("Throw %d\n", T++); for(int i = 0; i<sum; i++){ printf("%d", r[i]); printf(i == sum-1? "\n\n":" "); } } return 0; }