题意:
扫雷游戏,已知所有雷的位置。
每次可以点一个没翻开的不是雷的格子,如果当前格子是空白的,则周围的也翻开,直到周围一圈都是数字或者边界为止。不能翻的人输。
题解:
可以看作n堆石子,点击空白格子翻开的所有格子作一堆,每个数字格子是一颗石子,空白格子作一颗石子,不能通过点某个空白格子翻开的数字格子算单独的一颗一堆的石子。每堆要么每次取一颗,要么全取完(点空白的)。显然n只能转成n-1或者0。
我写挫了好多地方,WA了无数次才过……
//Time:234ms
//Memory:5244KB
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
#define MAXN 1010
#define FI first
#define SE second
#define MP(x,y) make_pair(x,y)
bool vi[MAXN][MAXN];
int ma[MAXN][MAXN];
const int dir[8][2]={{1,0},{0,1},{-1,0},{0,-1},{1,1},{1,-1},{-1,1},{-1,-1}};
int bfs(int x,int y)
{
int cnt=0;
queue<pair<int,int> > que;
que.push(MP(x,y));
while(que.size())
{
x=que.front().FI,y=que.front().SE;
que.pop();
vi[x][y]=1;
if(ma[x][y]==1)
{
++cnt;
continue;
}
for(int i=0;i<8;++i)
{
int tx=x+dir[i][0],ty=y+dir[i][1];
if(ma[tx][ty]==-2||ma[tx][ty]==1)
if(!vi[tx][ty])
vi[tx][ty]=1,que.push(MP(tx,ty));
}
}
return cnt?cnt+1:0;
}
int main()
{
//freopen("/home/moor/1003.txt","r",stdin);
int ncase,n,m,k,ans;
scanf("%d",&ncase);
for(int h=1;h<=ncase;++h)
{
scanf("%d%d%d",&n,&m,&k);
memset(ma,0,sizeof(ma));
memset(vi,0,sizeof(vi));
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
ma[i][j]=-2;
ans=0;
printf("Case #%d: ",h);
if(k==0)
{
printf("Xiemao\n");
continue;
}
for(int i=0;i<k;++i)
{
int a,b;
scanf("%d%d",&a,&b);
++a,++b;
ma[a][b]=-1;
for(int j=0;j<8;++j)
if(ma[a+dir[j][0]][b+dir[j][1]]==-2)
ma[a+dir[j][0]][b+dir[j][1]]=1;
}
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
if(!vi[i][j])
{
if(ma[i][j]==-1) continue;
if(ma[i][j]==-2)
{
int tmp=bfs(i,j);
ans^=(tmp==0)?0:(2-(tmp&1));
continue;
}
int tx,ty;
bool flag=0;
for(k=0;k<8&&!flag;++k)
{
tx=i+dir[k][0],ty=j+dir[k][1];
if(ma[tx][ty]==-2) flag=1;
}
if(!flag) ans^=1;
}
printf("%s\n",ans?"Xiemao":"Fanglaoshi");
}
return 0;
}