[题解] HDU 4101 Ali and Baba (BFS)

来源:互联网 发布:c语言 p 编辑:程序博客网 时间:2024/05/21 09:22

  题意:两人轮流开墙,每人一次只能开一个墙(或者打宝藏),打到宝藏的人胜利。
  分析:算出外面所有能敲的墙的数量,因为没人会傻到帮别人去开墙然后别人直接进去拿宝藏…再判断奇偶性,谁敲掉围绕这宝藏的那一圈墙谁就输了。
  在看到这一道题目时,我再一次(恬不知耻的)觉得:(*@ο@*) 哇~,好水啊!准备直接从-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;//懒得手写队列 X1queue <node> p;//懒得手写队列 X2void 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