hdu 4101 广搜
题意:n×m的棋盘上,0表示空格,可自由通过,-1表示宝石,正数k表示有一个值为k的石头,不能通过。两人轮流玩游戏,每次可以将一个从棋盘外围有路径可以到达的石头的值减1,若减为0则变为空格,可自由通过。问最后谁能拿到宝石。
分析:一开始以为是博弈,后来想想,发现如果甲将宝石外围的某石头(和宝石有路径相连的石头)变成了空格,则乙就能拿到宝石。所以他们只会选择和宝石不相通的石头,或者宝石外围的值大于1的石头。
于是先广搜一次,把宝石外围的石头标记一下。再从棋盘外围广搜,遇到石头,若是宝石外围的石头,则ans += val-1,val为石头的值。若是其它石头,ans += val。
为了方便,我在棋盘外围加了一圈空格,这样第二次搜索就可以从左上角开始,不用判断最外层哪些位置既可达又没有处理过。。。
const int M = 305; int n,m; int a[M][M],b[M][M]; LL cnt; int x[M*M], y[M*M], p; queue<int> q; int flag; void bfs1(int x1,int y1){ while(!q.empty())q.pop(); p=0; x[p]=x1; y[p]=y1; q.push(p); p++; while(!q.empty()){ int t=q.front(); q.pop(); x1=x[t]; y1=y[t]; FOR(i,0,4){ int xx=x1+dx[i], yy=y1+dy[i]; if(xx<1||xx>n||yy<1||yy>m){flag=true;return;} if(a[xx][yy]==0){ a[xx][yy]=-1; x[p]=xx; y[p]=yy; q.push(p); p++; }else if(a[xx][yy]>0) b[xx][yy]=1; } } } void bfs2(){ while(!q.empty())q.pop(); p=0; x[p]=0; y[p]=0; q.push(p); p++; while(!q.empty()){ int t=q.front(); q.pop(); int x1=x[t], y1=y[t]; FOR(i,0,4){ int xx=x1+dx[i], yy=y1+dy[i]; if(xx<0||xx>n+1||yy<0||yy>m+1) continue; if(a[xx][yy]>=0){ int temp=a[xx][yy]; a[xx][yy]=-2; if(b[xx][yy]) cnt+=temp-1; else { cnt+=temp; x[p]=xx; y[p]=yy; q.push(p); p++; } } } } } int main(){ #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); #endif while(~scanf("%d%d",&n,&m)){ int x, y; FOE(i,1,n) { FOE(j,1,m){ scanf("%d",&a[i][j]); if(a[i][j]==-1){x=i;y=j;} b[i][j]=0; } } FOE(i,0,n+1) a[i][0]=a[i][m+1]=b[i][0]=b[i][m+1]=0; FOE(j,0,m+1) a[0][j]=a[n+1][j]=b[0][j]=b[n+1][j]=0; flag=false; bfs1(x,y); if(flag){printf("Ali Win\n");continue;} cnt=0; bfs2(); if(cnt&1) printf("Ali Win\n"); else printf("Baba Win\n"); } return 0; }