• [博弈] hdu 3683 Gomoku


    题意:

    两个人下五子棋。给你现有棋盘,推断在三步之内的胜负情况。

    输出分为几种。

    1、棋盘不合法

    2、黑或白在第一步赢下在(x,y)点,多个输出x最小的、y最小的。

    3、输在第二步

    4、黑或白在第三步赢在(x,y)点,多个输出x最小的、y最小的。

    5、三步内不分胜负

    思路:

    首先先推断棋盘是否合法

    然后就是须要一个寻找当前我要下黑棋或者白棋在棋盘中我有几个必胜点。

    所谓的必胜点就是我下这个位置我能连五子或者以上。

    然后就是

    1、一步直接赢(我有一个或以上的必胜点)

    2、二步直接输(对方有两个以上的必胜点)

    3、对方有且仅仅有一个必胜点(我第一步堵上对方的必胜点。然后看我有没有2个必胜点,有我三步胜,没有三步内不分胜负)

    4、枚举我能够下的每个点,看看下完我有没有两个必胜点,有的话三步赢。没有的话三步内不分胜负。

    代码:

    #include"cstdlib"
    #include"cstdio"
    #include"cstring"
    #include"cmath"
    #include"queue"
    #include"algorithm"
    #include"iostream"
    using namespace std;
    int map[22][22];
    int move[8][2]= {{0,-1},{-1,-1},{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1}};
    int n;
    struct winpoint
    {
        int cnt,x,y;
        winpoint()
        {
            cnt=x=y=0;
        }
    };
    int dfs(int x,int y,int f,int key)
    {
        int xx=x,yy=y;
        int sum=0;
        while(1)
        {
            sum++;
            xx+=move[f][0];
            yy+=move[f][1];
            if(xx<0||yy<0||xx>=15||yy>=15) break;
            if(map[xx][yy]!=key) break;
        }
        return sum;
    }
    winpoint ok1(int key)
    {
        winpoint ans;
        for(int i=0; i<15; i++)
        {
            for(int j=0; j<15; j++)
            {
                if(map[i][j]!=-1) continue;
                int f=0;
                for(int k=0; k<4; k++)
                {
                    if(dfs(i,j,k,key)+dfs(i,j,k+4,key)-1>=5) f=1;
                    if(f) break;
                }
                if(f)
                {
                    if(ans.cnt==0)
                    {
                        ans.x=i;
                        ans.y=j;
                    }
                    ans.cnt++;
                }
            }
        }
        return ans;
    }
    int main()
    {
        while(scanf("%d",&n),n)
        {
            memset(map,-1,sizeof(map));
            int f=-1;
            int bl,wh;
            bl=wh=0;
            while(n--)
            {
                int x,y,z;
                scanf("%d%d%d",&x,&y,&z);
                map[x][y]=z;
                if(z) bl++;
                else wh++;
            }
            if(bl<wh||bl>=wh+2)   //不合法
            {
                puts("Invalid.");
                continue;
            }
            int key;
            if(bl==wh) key=1;
            else key=0;
            winpoint ans;
            ans=ok1(key);
    
            if(ans.cnt>=1)   //一步直接赢
            {
                printf("%s",key?

    "Place black ":"Place white "); printf("at (%d,%d) to win in 1 move. ",ans.x,ans.y); continue; } ans=ok1(key^1); if(ans.cnt>=2) //两个必胜点 直接输 { puts("Lose in 2 moves."); continue; } if(ans.cnt==1) //填对方必胜点 看是否能赢 { map[ans.x][ans.y]=key; winpoint tep=ok1(key); if(tep.cnt>=2) //对方堵不住 直接赢 { printf("%s",key?"Place black ":"Place white "); printf("at (%d,%d) to win in 3 moves. ",ans.x,ans.y); continue; } else //不能则不分胜负 { puts("Cannot win in 3 moves."); continue; } } for(int i=0; i<15; i++) //枚举每一个点 { for(int j=0; j<15; j++) { if(map[i][j]!=-1) continue; map[i][j]=key; winpoint tep=ok1(key); if(tep.cnt>=2) { printf("%s",key?

    "Place black ":"Place white "); printf("at (%d,%d) to win in 3 moves. ",i,j); f=1; } if(f==1) break; map[i][j]=-1; } if(f==1) break; } if(f==-1) puts("Cannot win in 3 moves."); } return 0; }



  • 相关阅读:
    php发送post请求的方法
    跨域请求的三种解决办法
    php验证码+js点击刷新
    13.mysql数据类型
    12.dateformat常用格式
    11.设计的三大范式
    nginx passwd (http://www.voidcn.com/article/p-suebfyqy-nx.html)
    删除文件 过滤某个文件
    mac必装软件
    elasticsearch 安装
  • 原文地址:https://www.cnblogs.com/gavanwanggw/p/7068129.html
Copyright © 2020-2023  润新知