• BFS-hdu-4101-Ali and Baba


    题目链接:

    http://acm.hdu.edu.cn/showproblem.php?pid=4101

    题目大意:
    给一个矩阵,0表示空的可走,-1宝藏的位置(只有一个),其余的正整数表示该位置石头数。甲乙两个人,轮流玩游戏。甲先玩,谁先从外面通过空路径到达了宝藏的位置(不能经过石头),谁就获胜。如果不能直接到达宝藏位置,可以从外面通过空到某个位置,拿走该位置上的一个石头,如果该位置没有石头则变成空的可走。

    解题思路:

    不错的BFS。

    首先如果甲能一步到达宝藏位置,则甲获胜。

    否则,一定有一个环包围着宝藏,则甲肯定不能先捅破这个环,不然乙一步就赢了。所以它尽可能的拿掉环外的石头,同理对于乙来说,也是尽可能的拿掉外面的石头,不能把环打破。

    所以只用统计外面石头总数以及环上每个位置留一个石头后的和即可。

    如果是奇数,说明甲恰好把最后一个环外的石头拿掉,此时乙必破环。甲胜,否则乙胜。

    bfs1() //从宝藏位置从内往外扫描,把该环标记。

    bfs2() //从边框bfs,如果走到了边界 +(hp-1) 否则为外面的点 +(hp)

    注意:

    6 7
    1  1  1  1  1  1  1
    1  0  0  0  0  0  1
    1  0  3  5  1  1  1
    1  0  -1 4  0  1  1
    1  0  1  0  0  1  1
    1  1  1  1  1  1  1 

    ans=16 不是22

    这组测试数据 计数的时候是不包括3,5的,因为环已经包括了。(wa了一上午)不能直接统计空的,非空的也要标记,只不过不放到队列中而已,要换个姿势。

    还有要注意这组测试数据:

    7 7
    1 1 1  1 1 1 1
    1 1 0  0 0 0 1
    1 0 0  1 0 0 1
    1 0 1  1 1 0 1
    1 0 0  1 0 0 1
    1 0 0 -1 0 0 1
    1 1 1  1 1 1 1

    环内有有数。

    代码:

    #include<iostream>
    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<string>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<set>
    #include<stack>
    #include<list>
    #include<queue>
    #define eps 1e-6
    #define INF 0x1f1f1f1f
    #define PI acos(-1.0)
    #define ll __int64
    #define lson l,m,(rt<<1)
    #define rson m+1,r,(rt<<1)|1
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    using namespace std;
    
    /*
    freopen("data.in","r",stdin);
    freopen("data.out","w",stdout);
    */
    
    
    #define Maxn 320
    int dir[4][2]={{-1,0},{0,1},{1,0},{0,-1}};
    int mm[Maxn][Maxn],n,m;
    bool vis[Maxn][Maxn];
    bool vis2[Maxn][Maxn];
    
    struct Node
    {
       int x,y;
    };
    Node s;
    
    bool isbor(int x,int y) //是否为边界
    {
       if(x==1||y==1||x==n||y==m)
          return true;
       return false;
    }
    bool iscan(int x,int y) //是否在
    {
       if(x<1||x>n||y<1||y>m)
          return false;
       return true;
    }
    
    bool bfs1()
    {
       memset(vis,false,sizeof(vis));
       queue<Node>myq;
       myq.push(s);
       vis[s.x][s.y]=true;
       if(isbor(s.x,s.y))
          return true;
       while(!myq.empty())
       {
          Node cur=myq.front();
          //printf(":%d %d
    ",cur.x,cur.y);
          myq.pop();
          for(int i=0;i<4;i++)
          {
             int xx=cur.x+dir[i][0],yy=cur.y+dir[i][1];
             if(!iscan(xx,yy))
                continue;
             if(isbor(xx,yy)&&mm[xx][yy]==0) //空位置 伸到了外面
                return true;
             if(vis[xx][yy]) 
                continue;
             vis[xx][yy]=true;
             if(mm[xx][yy]) //这也标记下 防止内部的干扰
                continue;
             Node tmp;
             tmp.x=xx,tmp.y=yy;
             myq.push(tmp);
             //printf("push:%d %d
    ",tmp.x,tmp.y);
          }
       }
       return false;
    }
    
    int bfs2()
    {
       int res=0;
       queue<Node>myq;
       myq.push(s);
       vis2[s.x][s.y]=true;
       //res+=mm[s.x][s.y];
       while(!myq.empty())
       {
          Node cur=myq.front();
          myq.pop();
          for(int i=0;i<4;i++)
          {
             int x=cur.x+dir[i][0],y=cur.y+dir[i][1];
            // printf("x:%d y:%d
    ",x,y);
             if(!iscan(x,y)||vis2[x][y]) //是否被访问了
                continue;
            vis2[x][y]=true;
            if(vis[x][y]) //如果是内边界
            {
               res+=(mm[x][y]-1); //直接+(hp-1)
               continue;
            }
            //其它的点 +hp
            Node tmp;
            tmp.x=x,tmp.y=y;
            res+=mm[x][y];
            myq.push(tmp);
          }
       }
       return res;
    }
    
    int main()
    {
       while(~scanf("%d%d",&n,&m))
       {
          for(int i=1;i<=n;i++)
             for(int j=1;j<=m;j++)
             {
                scanf("%d",&mm[i][j]);
                if(mm[i][j]==-1)
                   s.x=i,s.y=j;
             }
          if(bfs1())
          {
             printf("Ali Win
    ");
             continue;
          }
         /* putchar('
    ');
          for(int i=1;i<=n;i++)
          {
             for(int j=1;j<=m;j++)
                printf("%d ",vis[i][j]);
             putchar('
    ');
          }*/
          int ans=0;
          memset(vis2,false,sizeof(vis2)); //统计外围是否被访问了
          for(int i=1;i<=n;i++)
             for(int j=1;j<=m;j++)
             {
                if(isbor(i,j)) //从边界开始扫
                {
                   if(vis2[i][j]) //之前已经扫过了
                      continue;
                   vis2[i][j]=true;
                   if(vis[i][j]) //碰到了边界 直接+(hp-1)
                      ans+=(mm[i][j]-1);
                   else
                   {
                      ans+=mm[i][j]; //不是边界 加上然后继续扫
                      s.x=i,s.y=j;
                      ans+=bfs2();
                   }
                }
             }
         // printf(":%d
    ",ans);
          if(ans&1)
             printf("Ali Win
    ");
          else
             printf("Baba Win
    ");
       }
       return 0;
    }
    




  • 相关阅读:
    excel导出
    分页工具类
    orcale生成订单号---订单号的要求为:yyyyMMddHHmmss+000N
    spring data和spring嵌套使用 applictionContext.xml配置文件
    spring data jpa和spring嵌套使用 依赖引用
    spring data jpa 代码实现 增删改查
    一些常用的正则表达式
    mysql的两道实验题 涵盖sql语句基本操作方向
    Spring MVC 上传文件---配置文件
    Spring MVC 上传文件---代码实现
  • 原文地址:https://www.cnblogs.com/pangblog/p/3258006.html
Copyright © 2020-2023  润新知