ACM 1004 四子连棋(BFS)

本文探讨了1004题四子连棋的解决方案,使用宽度优先搜索(BFS)方法,旨在在4*4棋盘上通过最小步数使棋子形成四个一线的目标状态。给出了题目描述、输入输出说明,并附带了一个具体的样例输入及对应输出,展示如何求解最少步数达到目标棋局。
摘要由CSDN通过智能技术生成

在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋子,7颗黑色棋子,有两个空白地带,任何一颗黑白棋子都可以向上下左右四个方向移动到相邻的空格,这叫行棋一步,黑白双方交替走棋,任意一方可以先走,如果某个时刻使得任意一种颜色的棋子形成四个一线(包括斜线),这样的状态为目标棋局。

 
 

 

从文件中读入一个4*4的初始棋局,黑棋子用B表示,白棋子用W表示,空格地带用O表示。

用最少的步数移动到目标棋局的步数。

BWBO
WBWB
BWBW
WBWO

5


#include <iostream>
#include <cstring>

using namespace std;

#define MAX_N 4
#define MAX_Q 1000000
#define ADD(x) x=(x+1)%MAX_Q

struct Node
{
    int x[2],y[2];
    char mat[MAX_N][MAX_N+1];
    char Select;//Who play the chess
    int times;
} queue[MAX_Q],tmp;
int front,rear;

char mat[MAX_N][MAX_N+1];
int dx[]={1,-1,0,0};
int dy[]={0,0,1,-1};

bool CanVisit(Node &node,int x,int y)
{
    if(x<0 || x>=4 || y<0 || y>=4 || node.mat[y][x]!=node.Select)
    {
        return false;
    }

    return true;
}

bool OK(Node &node)
{
    for(int i=0;i<4;i++)
    {
        if(node.mat[i][0]==node.mat[i][1]
           && node.mat[i][1]==node.mat[i][2]
           && node.mat[i][2]==node.mat[i][3])
            return true;
    }

    if(node.mat[0][0]==node.mat[1][1]
       && node.mat[1][1]==node.mat[2][2]
       && node.mat[2][2]==node.mat[3][3])
            return true;

    if(node.mat[0][3]==node.mat[1][2]
       && node.mat[1][2]==node.mat[2][1]
       && node.mat[2][1]==node.mat[3][0])
           return true;

    for(int i=0;i<4;i++)
    {
        if(node.mat[0][i]==node.mat[1][i]
           && node.mat[1][i]==node.mat[2][i]
           && node.mat[2][i]==node.mat[3][i])
            return true;
    }

    return false;
}

int main()
{
    int ans=-1;
    int zcnt=0;
    int x[2],y[2];
    for(int i=0;i<4;i++)
    {
        cin>>mat[i];
    }

    for(int i=0;i<4;i++)
    for(int j=0;j<4;j++)
    {
        if(mat[i][j]=='O')
        {
            x[zcnt]=j;
            y[zcnt]=i;
            zcnt++;
        }
    }


    front=rear=0;
    memcpy(tmp.mat,mat,sizeof(mat));
    tmp.Select='B';
    tmp.times=0;
    tmp.x[0]=x[0];tmp.y[0]=y[0];
    tmp.x[1]=x[1];tmp.y[1]=y[1];
    queue[rear]=tmp;
    ADD(rear);
    tmp.Select='W';
    queue[rear]=tmp;
    ADD(rear);

    while(front!=rear)
    {
        tmp=queue[front];
        ADD(front);
        if(tmp.Select=='W') tmp.Select='B';
        else if(tmp.Select=='B') tmp.Select='W';

        for(int i=0;i<4;i++)
        {
            int nx=tmp.x[0]+dx[i],ny=tmp.y[0]+dy[i];

            if(CanVisit(tmp,nx,ny))
            {
                Node tmp2=tmp;

                tmp2.mat[ny][nx]='O';
                tmp2.x[0]=nx;tmp2.y[0]=ny;
                tmp2.mat[tmp.y[0]][tmp.x[0]]=tmp.Select;
                tmp2.times++;
                if(OK(tmp2))
                {
                    ans=tmp2.times;
                    goto EndFind;
                }
                queue[rear]=tmp2;
                ADD(rear);
            }
        }
        for(int i=0;i<4;i++)
        {
            int nx=tmp.x[1]+dx[i],ny=tmp.y[1]+dy[i];

            if(CanVisit(tmp,nx,ny))
            {
                Node tmp2=tmp;

                tmp2.mat[ny][nx]='O';
                tmp2.x[1]=nx;tmp2.y[1]=ny;
                tmp2.mat[tmp.y[1]][tmp.x[1]]=tmp.Select;
                tmp2.times++;
                if(OK(tmp2))
                {
                    ans=tmp2.times;
                    goto EndFind;
                }
                queue[rear]=tmp2;
                ADD(rear);
            }
        }
    }

EndFind:
    cout<<ans<<endl;

    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值