上个月比赛时候的题,今天终于给AC了。
主要看一个临界状态:-1被一圈1包围。这时候只要有人再拿了1个1,将打开包围-1的这个圈,那么下一个人肯定就是赢家。
所以只要数出这个圈外的石头个数即可。当然如果本来就不存在这个圈,即-1原本就靠近边界,那么就是A赢。
数圈外石头用BFS。为了方便,把这个圈成为墙。
首先第一个BFS从-1出发,标记包围-1的所有0.这样会得到这样一个状况:墙包围了所有被标记的0. 假如标记-1周围的非0,也就是试图标记这个墙的话,会将墙内的非0数字一同标记,实际上这些非0数字是没有用的。
第二个BFS从四个边界出发,因为已经保证了-1不可能在边界,也就是边界一定是墙外位置。将未被标记的数字累加。如果某位置上下左右某个临近位置有被标记的0则说明这里是墙,需要少拿一个石头保持临界状态,即总和减一。
得到墙外石头的个数之后就是很简单的博弈部分了。
奇数则A,偶数则B。
这个题其实数据有一点点水。。。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define MAXN 400
using namespace std;
int grid[MAXN][MAXN];
bool vis1[MAXN][MAXN];
bool vis2[MAXN][MAXN];
bool vis3[MAXN][MAXN];
bool out;
int sx,sy,sum,m,n;
int M[5][2]= {{1,0},{-1,0},{0,1},{0,-1}};
struct Point
{
int x,y;
Point(int a,int b):x(a),y(b) {}
};
void bfs_1()
{
memset(vis1,0,sizeof(vis1));
out=false;
Point st(sx,sy);
vis1[sx][sy]=true;
queue<Point> q;
q.push(st);
while(!q.empty())
{
Point tmp=q.front();
q.pop();
for(int i=0; i<4; ++i)
{
int xx=tmp.x+M[i][0],yy=tmp.y+M[i][1];
if(xx<1||xx>m||yy<1||yy>n)
{
out=true;
return ;
}
if(vis1[xx][yy]) continue;
if(grid[xx][yy]==0)
{
vis1[xx][yy]=true;
Point t(xx,yy);
q.push(t);
}
else continue;
}
}
}
bool Judge(Point p)
{
for(int k=0; k<4; ++k)
{
int xx=p.x+M[k][0],yy=p.y+M[k][1];
if(vis1[xx][yy]) return true;
}
return false;
}
void _BFS_2(int i,int j)
{
if(vis1[i][j]||vis2[i][j]) return ;
Point st(i,j);
vis2[i][j]=true;
sum+=grid[i][j];
queue<Point> q;
q.push(st);
while(!q.empty())
{
Point tmp=q.front();
q.pop();
if(Judge(tmp))
{
sum--;
continue;
}
for(int k=0; k<4; ++k)
{
int xx=tmp.x+M[k][0],yy=tmp.y+M[k][1];
if(xx<1||xx>m||yy<1||yy>n) continue;
if(vis2[xx][yy]) continue;
sum+=grid[xx][yy];
vis2[xx][yy]=true;
Point t(xx,yy);
q.push(t);
}
}
}
void bfs_2()
{
memset(vis2,0,sizeof(vis2));
memset(vis3,0,sizeof(vis3));
sum=0;
for(int i=1; i<=m; ++i)
{
_BFS_2(i,1);
_BFS_2(i,n);
}
for(int i=1; i<=n; ++i)
{
_BFS_2(1,i);
_BFS_2(m,i);
}
}
int main()
{
while(scanf("%d%d",&m,&n)!=EOF)
{
memset(grid,0,sizeof(grid));
for(int i=1; i<=m; ++i)
for(int j=1; j<=n; ++j)
{
scanf("%d",&grid[i][j]);
if(grid[i][j]==-1)
{
sx=i;
sy=j;
}
}
bfs_1();
if(out) puts("Ali Win");
else
{
bfs_2();
if(sum%2) puts("Ali Win");
else puts("Baba Win");
}
}
return 0;
}