zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    bzoj1648:奶牛野餐
    bzoj1650:跳石子
    bzoj1643:贝西的秘密草坪
    bzoj1639:月度开支
    bzoj1636:Balanced Lineup
    bzoj1634:护花
    .
    bzoj1620:时间管理
    bzoj1611:流星雨
    bzoj1609:麻烦的聚餐
  • 原文地址:https://www.cnblogs.com/zeroform/p/7710834.html
Copyright © 2011-2022 走看看