wikioi1004四子连棋

本文介绍了一种使用广度优先搜索(BFS)算法解决特定棋盘游戏问题的方法。通过将棋盘状态编码为整数并利用哈希表进行状态判重,有效地避免了重复搜索,最终找到使一方获胜所需的最少步数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这题是一题搜索题,我用广搜。

还有一个主要的是判重,我把棋盘当成一个3进制数,然后转化成十进制,再mod一个大质数,我用的大质数是3733799

照理说实际上存在大量冗余,因为11440*36=411840,每个状态出现一次,但是3进制一共要3^16=43046721,大了100倍。

然后就是广搜了。

定义了一个结构体aaa,struct aaa{int map[5][5];int yan,bu;int x[2],y[2];int xx,yy;};

map代表进行了这一步后的棋盘。yan代表到达这一个map的最后一步的颜色,用0、1表示。bu代表走了几步。x,y记录两个空格的位置,xx,yy记录上一步走动的棋后来的位置。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cstdlib>
using namespace std;
int move[8][2]={{1,0},{-1,0},{0,1},{0,-1},{1,1},{-1,-1},{-1,1},{1,-1}};
struct aaa{int map[5][5];int yan,bu;int x[2],y[2];int xx,yy;};
bool hash[3800000];
int sheng(int map1[5][5]);
bool panduan(int map1[5][5],int yan,int zix,int ziy);
int main()
{
    queue<aaa>la;
    aaa first;
    int k=0;
    for(int i=1;i<=4;i++)
        for(int j=1;j<=4;j++)
    {
        char a;
        cin>>a;
        if(a=='B')first.map[i][j]=1;
        else if(a=='W')first.map[i][j]=2;
        else {first.map[i][j]=0;first.x[k]=i;first.y[k]=j;k++;}
    }
    aaa a1;
    for(int i=1;i<=4;i++)
        for(int j=1;j<=4;j++)
    {
        if(first.map[i][j]!=0)
        if(panduan(first.map,first.map[i][j],i,j)){cout<<0;return 0;}


    }
    for(int i=0;i<2;i++)
    {
       for(int j=0;j<4;j++)
       {
           int x,y;
           x=first.x[i]+move[j][0];
           y=first.y[i]+move[j][1];
           if(x>0&&x<=4&&y>0&&y<=4&&(first.map[x][y]!=0)){
            a1.x[0]=x;
            a1.y[0]=y;
            a1.yan=first.map[x][y];
            a1.bu=1;
            a1.xx=first.x[i];
            a1.yy=first.y[i];
            for(int ii=1;ii<=4;ii++)
                for(int jj=1;jj<=4;jj++)
                a1.map[ii][jj]=first.map[ii][jj];
            swap(a1.map[x][y],a1.map[a1.xx][a1.yy]);
            a1.x[1]=first.x[1-i];
            a1.y[1]=first.y[1-i];
            la.push(a1);
           }
       }
    }
    while(!la.empty()){
        aaa key=la.front();
        la.pop();
        int k=sheng(key.map)%3733799;
        if(!hash[k])
        {
            hash[k]=true;
            if(panduan(key.map,key.yan,key.xx,key.yy)){
                cout<<key.bu;
                return 0;
            }
            for(int i=0;i<=1;i++)
                for(int j=0;j<4;j++){
                 aaa a1;
                 int x,y;
                 x=key.x[i]+move[j][0];
                 y=key.y[i]+move[j][1];
                 if(x>0&&x<=4&&y>0&&y<=4&&key.map[x][y]+key.yan==3){
            a1.x[1-i]=key.x[1-i];
            a1.y[1-i]=key.y[1-i];
            a1.x[i]=x;
            a1.y[i]=y;
            a1.yan=3-key.yan;
            a1.bu=key.bu+1;
            a1.xx=key.x[i];
            a1.yy=key.y[i];
            for(int ii=1;ii<=4;ii++)
                for(int jj=1;jj<=4;jj++)
                a1.map[ii][jj]=key.map[ii][jj];
            swap(a1.map[x][y],a1.map[a1.xx][a1.yy]);
            la.push(a1);
                }
            }


        }


    }
    return 0;
}
int sheng(int map1[5][5])
{
    int ans=0;
    for(int i=1;i<=4;i++)
        for(int j=1;j<=4;j++)
    {
        ans=ans*3+map1[i][j];
    }
    return ans;
}
bool panduan(int map1[5][5],int yan,int zix,int ziy)
{
    int k=0;
    for(int i=0;i<4;i++)
    {
        k=1;
        for(int j=0;j<=1;j++)
        {int i1=i*2+j;
        int x=zix+move[i1][0],y=ziy+move[i1][1];
        while(x>0&&x<=4&&y>0&&y<=4){
            if(map1[x][y]==yan){k++;x+=move[i1][0];y+=move[i1][1];}
            else break;
            if(k==4)return true;
            }
        }
    }
return false;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值