题意:两人轮流开墙,每人一次只能开一个墙(或者打宝藏),打到宝藏的人胜利。
分析:算出外面所有能敲的墙的数量,因为没人会傻到帮别人去开墙然后别人直接进去拿宝藏…再判断奇偶性,谁敲掉围绕这宝藏的那一圈墙谁就输了。
在看到这一道题目时,我再一次(恬不知耻的)觉得:(*@ο@*) 哇~,好水啊!准备直接从-1开始BFS,然后将在内部的所有点的数量记录下来,然后用总点数去减去内部点数再判断奇偶性即可得到答案。
BUT,WA WA WA使我不得不冷静下来,重新看代码…
原来是有一种情况没有考虑到。
For example
7 7
1 1 1 1 1 1 1
1 1 0 -1 0 0 1
1 0 1 1 1 0 1
1 0 1 1 1 0 1
1 0 1 1 1 0 1
1 0 0 0 0 0 1
1 1 1 1 1 1 1
这样的数据,第四行,第四个数据就无法读取到,于是乎,瞬间爆炸
那么怎么解决呢?——双BFS
双BFS的思路是这样的,将第一次从-1开始扩展得到的点全部标记(其实就是判重数组吗),然后从外往内BFS一遍,如果搜到的是没有标记过的点,入队,将这个点HP敲完;要是标记过,不入队,将这个点HP敲到剩下1滴。那么,敲掉HP的总数即为判断的依据。
并且要记得,如果第一遍搜出了图,那么说明宝藏直接和外界相连哦,那么Ali就直接赢了。
看代码↓↓↓
#include <bits/stdc++.h>
using namespace std;
bool flag=0;
int n,m,stx,sty,sum=0,total=0;
int MAP[310][310];
bool pd[310][310];
bool pdc[310][310];
int mo[4][2]={1,0,0,1,-1,0,0,-1};
struct node {
int x,y;
}st;
queue <node> q;//懒得手写队列 X1
queue <node> p;//懒得手写队列 X2
void input() {
int i,j;
for(i=0;i<n;i++) {
for(j=0;j<m;j++) {
scanf("%d",&MAP[i][j]);
if(MAP[i][j]==-1) {
st.x=i;
st.y=j;
}
else {
sum+=MAP[i][j];
}
}
}
return;
}
bool bfs2() {//从外往内
int nx,ny,i,j;
while(!p.empty()) {p.pop();}
for(i=0;i<n;i++) {
p.push(node{i,-1});
p.push(node{i,m});
}
for(j=0;j<m;j++) {
p.push(node{-1,j});
p.push(node{n,j});
}
while(!p.empty()) {
node now=p.front();
p.pop();
for(int i=0;i<=3;i++) {
nx=now.x+mo[i][0];
ny=now.y+mo[i][1];
if(nx>=0 && nx<n && ny>=0 && ny<m) {
if(!pdc[nx][ny]) {
pdc[nx][ny]=1;
if(pd[nx][ny]) {
total+=MAP[nx][ny]-1;
}
else {
total+=MAP[nx][ny];
p.push(node{nx,ny});
}
}
}
}
}
if(total&1) {return 1;}
return 0;
}
bool bfs1() {//从内往外
int nx,ny;
while(!q.empty()) {q.pop();}
q.push(st);
pd[st.x][st.y]=1;
while(!q.empty() && !flag) {
node now=q.front();
q.pop();
for(int i=0;i<=3;i++) {
nx=now.x+mo[i][0];
ny=now.y+mo[i][1];
if(nx>=0 && nx<n && ny>=0 && ny<m) {
if(pd[nx][ny]) continue;
if(MAP[nx][ny]==0) {
q.push(node{nx,ny});
pd[nx][ny]=1;
}
else if(MAP[nx][ny]>=1) {
pd[nx][ny]=1;
}
}
else {flag=1;break;}
}
if(flag) {break;}
}
if(flag) {return 1;}//要是搜出去了,直接Ali赢
bfs2();
}
int main() {
while(~scanf("%d%d",&n,&m)) {
memset(MAP,0,sizeof(MAP));
memset(pd,0,sizeof(pd));
memset(pdc,0,sizeof(pdc));
total=0;sum=0;flag=0;
input();
if(bfs1()) printf("Ali Win\n");
else printf("Baba Win\n");
}
return 0;
}
From:Chlience