码迷,mamicode.com
首页 > 其他好文 > 详细

[博弈] hdu 3683 Gomoku

时间:2017-06-23 10:20:42      阅读:110      评论:0      收藏:0      [点我收藏+]

标签:rac   最小   hit   iostream   val   没有   printf   pre   key   

题意:

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

输出分为几种。

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.\n",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.\n",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.\n",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; }



[博弈] hdu 3683 Gomoku

标签:rac   最小   hit   iostream   val   没有   printf   pre   key   

原文地址:http://www.cnblogs.com/gavanwanggw/p/7068129.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!