首页 > 代码库 > HDU 3683 模拟&搜索

HDU 3683 模拟&搜索

给出五子棋残局,判断三步内是否能分出胜负,玩家为当前该走旗子的颜色,下一步为白棋或黑棋不定。

按照顺序判断即可:

1:判断棋盘是否合法,并确定玩家颜色

2:判断当前玩家颜色是否有一个必胜点,有玩家则在第一步胜

3:判断另一方在当前是否有两个必胜点,若有,则玩家在第二步失败

4:BFS出玩家是否存在此方案:任意放置一个位置的前提下,另一方没有必胜点,且玩家有两个必胜点,则玩家在第三步胜

5:否则3步内无法分出胜负


#include "stdio.h"
#include "string.h"

int dir[4][2]={{-1,0},{-1,1},{0,1},{1,1}};

int map[21][21];
int ans_x,ans_y;

int ok1(int key)
{
    int i,j,x,y,k,sum;
    for (i=0;i<15;i++)
        for (j=0;j<15;j++)
        if (map[i][j]==-1)
        {
            for (k=0;k<4;k++)
            {
                x=i; y=j; sum=1;
                while (1)
                {
                    x+=dir[k][0];
                    y+=dir[k][1];
                    if (x<0 || x>=15 || y<0 || y>=15) break;
                    if (map[x][y]!=key) break;
                    sum++;
                }
                x=i;y=j;
                while (1)
                {
                    x-=dir[k][0];
                    y-=dir[k][1];
                    if (x<0 || x>=15 || y<0 || y>=15) break;
                    if (map[x][y]!=key) break;
                    sum++;

                }
                if (sum>=5) { ans_x=i; ans_y=j; return 1;}
            }
        }
    return -1;
}

int ok2(int key)
{
    int i,j,k,x,y,sum,ok;
    ok=0;
    for (i=0;i<=14;i++)
        for (j=0;j<=14;j++)
        if (map[i][j]==-1)
        {
            for (k=0;k<4;k++)
            {
                sum=1;
                x=i; y=j;
                while (1)
                {
                    x+=dir[k][0];
                    y+=dir[k][1];
                    if (x<0 || x>=15 || y<0 || y>=15) break;
                    if (map[x][y]!=key) break;
                    sum++;
                }
                x=i; y=j;
                while (1)
                {
                    x-=dir[k][0];
                    y-=dir[k][1];
                    if (x<0 || x>=15 || y<0 || y>=15) break;
                    if (map[x][y]!=key) break;
                    sum++;
                }
                if (sum>=5) {ok++;break;}
            }
            if (ok==2) return 1;
        }
        return -1;
}


int bfs(int key)
{
    int i,j;
    for (i=0;i<15;i++)
        for (j=0;j<15;j++)
        if (map[i][j]==-1)
        {
            map[i][j]=key;
            if (ok1(1-key)==-1 && ok2(key)==1)
            {
            ans_x=i; ans_y=j;
            return 1;
            }
            map[i][j]=-1;
        }
    return -1;
}

int main()
{
    int n,i,a,b,c,blk,wt,first,ans;
    while (scanf("%d",&n)!=EOF)
    {
        if (n==0) break;

        blk=wt=0;
        memset(map,-1,sizeof(map));
        for (i=1;i<=n;i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            map[a][b]=c;
            if (c==1) blk++; else wt++;
        }

        if (blk==wt) first=1;
        else
            if (blk==wt+1) first=0;
        else
        {
            printf("Invalid.\n");
            continue;
        }

        ans=ok1(first); // 第一步存在必胜点
        if (ans==1)
        {
            printf("Place ");
            if (first==1) printf("black "); else printf("white ");
            printf("at (%d,%d) to win in 1 move.\n",ans_x,ans_y);
            continue;
        }

        ans=ok2(1-first); // 另一方存在两个必胜点
        if (ans==1)
        {
            printf("Lose in 2 moves.\n");
            continue;
        }

        ans=bfs(first); // 搜索是否存在第三步定胜负

        if (ans==1)
        {
            printf("Place ");
            if (first==1) printf("black "); else printf("white ");
            printf("at (%d,%d) to win in 3 moves.\n",ans_x,ans_y);
            continue;
        }
        else
            printf("Cannot win in 3 moves.\n");

    }
    return 0;

}


HDU 3683 模拟&搜索