poj1753 Flip Game 状态压缩+bfs

来源:互联网 发布:提额软件 编辑:程序博客网 时间:2024/05/20 00:17

传送门:poj1753 Flip Game

题目的大意

在一个4*4的方格里面放黑或者白之一的卡片,当选中一个的,选中的那个就会翻转(如果是白色变为黑色,如果是黑色变为白色),伴随着他四周(上下左右)的的卡片也会翻转。就像下面这种情况题目中原图
如图所示,假设我们点击第三行第一列的时候不仅仅第三行第一列会变换状态,相应的第二行第一列,第三行第二列,第四行第一列也会变换,当然如果左边有的话也会变换状态。上图对应输入为:

bwbw wwww bbwb bwwb

当点击完第三行第一列的时候,会变为下面的状态:

bwbw bwww wwwb wwwb 

w代表white白色,b代表black黑色
输入:输入4*4只包含b或者w的矩阵
输出:通过几次能改变为全为白色或者全为黑色,如果不能输入impossible

解题思路

bfs+状态压缩
棋盘一共是有16方格,也就意味着有2^16(65535)种状态,
我们就假设黑色的棋子的状态为0,白色状态的棋子为1
每种方格只能被点击一次,比如我们在一个全为黑色点击了左上角的棋子,棋盘如下:

bbbbbbbbbbbbbbbb

抽象为对应的状态棋盘就变为

0000000000000000

点击左上角的棋子之后,状态棋盘就变为:

1100100000000000

我们默认上面的和左边的高位,所以对应的二进制转换为十进制就变为51200
当点击其他的时候也是一样的原因。
有了这16中状态我们就可以通过异或来得到点击完相应的棋子之后的状态。

AC代码

#include<cstdio>#include<string>#include<cstring>#include<cmath>#include<algorithm>#include<queue>#include<set>#include<iostream>#include<stack>using namespace std;struct Node{    int state;    int step;};bool visit[65536];int change[16] = //这个是点击每个棋子的状态{     51200,58368,29184,12544,     35968,20032,10016,4880,     2248,1252,626,305,     140,78,39,19};int bfs(int state){     memset(visit,false,sizeof(visit));    Node cur;    Node next;    int i,j;    cur.step = 0;    cur.state= state;    visit[state] = true;    queue<Node>q;    q.push(cur);    while(!q.empty())    {        cur = q.front();        q.pop();        if(cur.state == 0 || cur.state == 0xffff)//当全为白或者全为黑的情况            return cur.step;        for(i=0;i<16;i++)//一共有16个棋子        {            next.state = cur.state^change[i];//得到点击棋子之后的状态            next.step = cur.step+1;          //步骤+1            if(next.state == 0 || next.state == 0xffff)                return next.step;            if(visit[next.state])  //已经遍历过中的状态                continue;            visit[next.state] = true;//如果没有遍历过这种状态,改变为遍历过            q.push(next);//添加到队列中        }    }    return -1;}int main(){    int i,j,state,ans;    char theMap[5][5];    while(scanf("%s",theMap[0])!=EOF)    {        for(i=1;i<4;i++)            scanf("%s",theMap[i]);        state = 0;        for(i=0;i<4;i++)    //变输入变把原棋盘的二进制计算出来            for(j=0;j<4;j++)            {                state <<= 1;                if(theMap[i][j] == 'b')                    state+=1;            }        //printf("[%d]\n",state);        ans = bfs(state);        if(ans == -1)            printf("Impossible\n");        else            printf("%d\n",ans);    }    return 0;}
0 0
原创粉丝点击