Ancient Go

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)
Total Submission(s): 1649    Accepted Submission(s): 525


Problem Description
Yu Zhou likes to play Go with Su Lu. From the historical research, we found that there are much difference on the rules between ancient go and modern go.

Here is the rules for ancient go they were playing:

The game is played on a 8×8 cell board, the chess can be put on the intersection of the board lines, so there are 9×9 different positions to put the chess.
Yu Zhou always takes the black and Su Lu the white. They put the chess onto the game board alternately.
The chess of the same color makes connected components(connected by the board lines), for each of the components, if it's not connected with any of the empty cells, this component dies and will be removed from the game board.
When one of the player makes his move, check the opponent's components first. After removing the dead opponent's components, check with the player's components and remove the dead components.
One day, Yu Zhou was playing ancient go with Su Lu at home. It's Yu Zhou's move now. But they had to go for an emergency military action. Little Qiao looked at the game board and would like to know whether Yu Zhou has a move to kill at least one of Su Lu's chess.
 

Input
The first line of the input gives the number of test cases, T(1T100). T test cases follow. Test cases are separated by an empty line. Each test case consist of 9 lines represent the game board. Each line consists of 9 characters. Each character represents a cell on the game board. . represents an empty cell. x represents a cell with black chess which owned by Yu Zhou. o represents a cell with white chess which owned by Su Lu.
 

Output
For each test case, output one line containing Case #x: y, where x is the test case number (starting from 1) and y is Can kill in one move!!! if Yu Zhou has a move to kill at least one of Su Lu's components. Can not kill in one move!!! otherwise.
 

Sample Input
2 .......xo ......... ......... ..x...... .xox....x .o.o...xo ..o...... .....xxxo ....xooo. ......ox. .......o. ...o..... ..o.o.... ...o..... ......... .......o. ...x..... ........o
 

Sample Output
Case #1: Can kill in one move!!! Case #2: Can not kill in one move!!!
Hint
In the first test case, Yu Zhou has 4 different ways to kill Su Lu's component. In the second test case, there is no way to kill Su Lu's component.
 

Source



思路:
这个题是在看了题解的情况下才写出来的。。。
题意是,现在有一个9*9棋盘,我方棋子是'x',敌方是'o'。现在轮到我方落子,问我方能不能在下一回合吃掉对方的至少一个棋子。吃掉的规则是:对方被围的棋子在下一回合时已经找不到为' . '的位置。因为数据量很小, 9X9的棋盘,所以用dfs随便搜,对同一个连通块来说判断其周围'.'的个数是不是为1 ,一定要注意避免重复计数(自己想象下同一个'.'为一个连通块的不同'o'的边界) 为了完成 对同一个'.'不用连通块可以访问多次,同一连通块只能访问一次 的效果,那么就用visit数组zai对点标记看它是否已经到达过。因为每次对一个点dfs的时候都要使它的过程是独立的,所以再用一个newvisit数组来进行每次dfs的标记。所以在dfs里面走过一个新的点的时候要同时对visit和newvisit两个数组进行标记更新。


代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;

char str[15][15];
bool visit[15][15],newvisit[15][15];
int dir[4][2] = {{0,1},{0,-1},{1,0},{-1,0}};
int s;

void dfs(int x,int y)
{
    for(int i=0;i<4;i++)
    {
        int dx=x+dir[i][0];
        int dy=y+dir[i][1];
        if(dx<0||dx>=9||dy<0||dy>=9) continue;
        if(str[dx][dy]=='.'&&newvisit[dx][dy]==0)///看看这个区域里面有多少个‘.’  要避免重复就用ww标记
        {
            newvisit[dx][dy]=1;
            s++;
        }
        if(str[dx][dy]=='o'&&visit[dx][dy]==0)///区域增加
        {
            visit[dx][dy]=1;
            dfs(dx,dy);
        }
    }
}


int main()
{
	int t;
    while(scanf("%d", &t)!=EOF)
    {
        for(int num=1; num<=t; num++)
	    {
	        for(int i=0; i<9; i++)
	        {
	            scanf("%s", str[i]);
	        }
	        memset(visit, 0, sizeof(visit));
			int ans=0;
	        for(int i=0; i<9; i++)
		    {
		        for(int j=0; j<9; j++)
		        {
		            if(str[i][j]=='o'&&visit[i][j]==0)
		            {
		                visit[i][j]=1;
		                s=0;
		                memset(newvisit,0,sizeof(newvisit));
	                    dfs(i,j);
	                    if(s<=1)///如果满足 就可以封死  
	                    {
	                        ans=1;
	                        break;
	                    }
		            }
		        }
		    }       
	        if(ans)
	            printf("Case #%d: Can kill in one move!!!\n", num);
	        else
	            printf("Case #%d: Can not kill in one move!!!\n", num);
	    }	
    }
    return 0;
}