luogu P2346 四子连棋

原题链接:https://www.luogu.org/problem/show?pid=2346

第一次写搜索一遍过,纪念一下先。

论结构体的妙用,直接传一个数组简直太方便。用一个数组记录当前的局面,2为白色,1为黑色,0为空格,已走的步数,下一步那一方走,1为白色,-1为黑色。

然后把初始局面的两种走法都加进队列中,并标记,这里一定要取模,3^16有四千多万,bool数组也不好受

当找到一个空白的格子时,就试试能否移动,如果移动后能形成一个新局面,就加进队列,加进队列之前可以先特判一下是否能结束。虽然是广搜,但是还是要把局面恢复。

 

#include<cstdio>
#include<cstdlib>
#include<queue>
const int c=1000007;
using namespace std;
char s[10];
struct mat
{
    int c[5][5],nxt,s;
}stb,stw;
bool b[2000005][3];
int sum;
int nx[5]={0,0,1,0,-1};
int ny[5]={0,1,0,-1,0};
queue<mat>q;
int vis(mat x,int ns)
{
    sum=0;
    for(int i=4;i>=1;i--)
    {
        for(int j=4;j>=1;j--) sum=sum*3+x.c[i][j];
    }
    sum%=c;
    if(b[sum][ns+1]==1) return 1;
    else
    {
        b[sum][ns+1]=1;
        return 0;
    }
}
int win(mat x)
{
    for(int i=1;i<=4;i++) if(x.c[i][1]==x.c[i][2]&&x.c[i][1]==x.c[i][3]&&x.c[i][1]==x.c[i][4]) return 1;
    for(int i=1;i<=4;i++) if(x.c[1][i]==x.c[2][i]&&x.c[1][i]==x.c[3][i]&&x.c[1][i]==x.c[4][i]) return 1;
    if(x.c[1][1]==x.c[2][2]&&x.c[1][1]==x.c[3][3]&&x.c[1][1]==x.c[4][4]) return 1;
    if(x.c[1][4]==x.c[2][3]&&x.c[1][4]==x.c[3][2]&&x.c[1][4]==x.c[4][1]) return 1;
    return 0;
}
void move(mat g,int x,int y,int ns)
{
    mat t=g;t.nxt=ns;t.s=g.s+1;
    for(int i=1;i<=4;i++)
    {
        int tx=x+nx[i],ty=y+ny[i];
        if(tx<1||tx>4||ty<1||ty>4) continue;
        if((ns==1&&t.c[tx][ty]==2)||(ns==-1&&t.c[tx][ty]==1))
        {
            t.c[x][y]=t.c[tx][ty];
            t.c[tx][ty]=0;
            if(win(t)==1)
            {
                printf("%d",t.s);
                exit(0);
            }
            if(vis(t,ns)==0) q.push(t);
            t.c[tx][ty]=t.c[x][y];
            t.c[x][y]=0;
        }
    }
}
void bfs()
{
    q.push(stb);q.push(stw);
    while(!q.empty())
    {
        mat t=q.front();q.pop();
        for(int i=1;i<=4;i++)
        {
            for(int j=1;j<=4;j++)
            {
                if(t.c[i][j]==0) move(t,i,j,-t.nxt);
            }
        }
    }
}
int main()
{
    for(int i=1;i<=4;i++)
    {
        scanf("%s",s);
        for(int j=1;j<=4;j++)
        {
            if(s[j-1]=='O')
            {
                stb.c[i][j]=0;
                stw.c[i][j]=0;
            }
            if(s[j-1]=='W')
            {
                stb.c[i][j]=2;
                stw.c[i][j]=2;
            }
            if(s[j-1]=='B')
            {
                stb.c[i][j]=1;
                stw.c[i][j]=1;
            }
        }
    }
    stb.nxt=-1;
    stw.nxt=1;
    vis(stw,1);vis(stb,-1);
    bfs();
    return 0;
}

 

posted @ 2017-10-22 17:33  Excim  阅读(238)  评论(0编辑  收藏  举报