• poj 1753 Flip Game 枚举(bfs+状态压缩)


    题目:http://poj.org/problem?id=1753

    因为粗心错了好多次……,尤其是把1<<15当成了65535;

    参考博客:http://www.cnblogs.com/kuangbin/archive/2011/07/30/2121677.html

    主要思想:

    1.如果用一个4*4的数组存储每一种状态,不但存储空间很大,而且在穷举状态时也不方便记录。因为每一颗棋子都只有两种状态,所以可以用二进制0和1表示每一个棋子的状态,则棋盘的状态就可以用一个16位的整数唯一标识。而翻转的操作也可以通过通过位操作来完成。显然当棋盘状态id为0(全白)或65535(全黑)时,游戏结束。

    2.对于棋盘的每一个状态,都有十六种操作,首先要判断这十六种操作之后是否有完成的情况,如果没有,则再对这十六种操作的结果分别再进行上述操作,显然这里就要用到队列来存储了。而且在翻转的过程中有可能会回到之前的某种状态,而这种重复的状态是不应该再次入队的,所以维护isVis[i]数组来判断id==i的状态之前是否已经出现过,如果不是才将其入队。如果游戏无法完成,状态必定会形成循环,由于重复状态不会再次入队,所以最后的队列一定会是空队列。

    3.由于0^1=1,1^1=0,所以翻转的操作可以通过异或操作来完成,而翻转的位置可以通过移位来确定。

    #include<stdio.h>
    #include<string.h>
    #include<queue>
    
    using namespace std;
    
    int id,vis[1<<17];
    struct node
    {
        int x,step;
    };
    
    int bfs()
    {
        queue<node>q;
        int i;
        struct node pos,cur;
        if(id==0||id==65535)
        return 0;
    
        memset(vis,0,sizeof(vis));
        pos.step=0;
        pos.x=id;
    
        q.push(pos);
        vis[id]=1;
    
        while(!q.empty())
        {
            cur=q.front();
            q.pop();
            for(i=0; i<=15; i++)
            {
                pos.x=(cur.x^(1<<i));
    
                if(i+4<16)     pos.x^=(1<<(i+4));
                if(i-4>=0)      pos.x^=(1<<(i-4));
                if(i%4!=0)  pos.x^=(1<<(i-1));
                if((i+1)%4!=0)  pos.x^=(1<<(i+1));
    
                if(vis[pos.x]==0)
                {
                    vis[pos.x]=1;
                    pos.step=cur.step+1;
                    q.push(pos);
                }
    
                if(pos.x==0||pos.x==65535)
                return pos.step;
            }
        }
    
        return -1;
    };
    
    int main()
    {
        int i,f,j;
        char c;
        id=0;
    
        for(i=0; i<4; i++)
        {
            for(j=0; j<4; j++)
            {
                id=(id<<1);
                scanf("%c",&c);
                if(c=='b')
                    id+=1;
                else
                    id+=0;
            }
            getchar();
        }
         f=bfs();
    
        if(f==-1)
            printf("Impossible
    ");
        else
            printf("%d
    ",f);
    }
    

      

  • 相关阅读:
    OO第二单元——多线程(电梯)
    OO前三次作业思考(第一次OO——Blog)
    P2016 战略游戏——树形DP大水题
    P1108 低价购买——最长下降子序列+方案数
    P1041 传染病控制——暴力遍历所有相同深度的节点
    P2502 [HAOI2006]旅行——暴力和并查集的完美结合
    2019.10.25字符串——zr
    P3719 [AHOI2017初中组]rexp——递归模拟
    树状数组优化最长上升子序列
    P1378 油滴扩展——搜索小记
  • 原文地址:https://www.cnblogs.com/bfshm/p/3147364.html
Copyright © 2020-2023  润新知