您的位置:首页 > 其它

poj1753 Flip Game(BFS+位压缩)

2017-11-13 11:00 405 查看

题目链接

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

题意

一个棋盘上有16个格子,按4×4排列,每个格子有两面,两面的颜色分别为黑色和白色,游戏的每一轮选择一个格子翻动,翻动该格子意味着将该格子及其上下左右格子(如果存在的话)的黑面朝上变成白面朝上,反之亦然,游戏的目标是格子全部黑面朝上或者全部白面朝上。输入棋盘的初始状态,求最少经过多少轮可以达到游戏的目标。

思路

求最少轮数,我会想到使用bfs来解决(dfs也可以解决),但使用bfs求解,如果每个状态都直接存储下当前棋盘的话,会消耗很大内存,运算速度也非常慢,如果把黑色格子(b)看成1,白色格子(w)看成0,则16个格子对应一个16位的二进制数,可以用一个int来存储,这样就解决了内存消耗及运算速度的问题了。当棋盘状态为全白0x0000(0)或者全黑0xffff(65535)时,游戏结束。还有一个问题是用二进制位表示的棋盘如何进行翻转。假设当前棋盘为0000 0000 0000 0000,对第0行第0列位置(0,0)进行翻转,翻转后的棋盘为1100 1000 0000 0000,对应的十进制数为51200。我们也可以对剩下的15个位置进行翻转,这样可以得到16个十进制数,对应对棋盘的16个位置进行翻转操作。对于任意一个棋盘状态(十进制数表示为n)来说,如果要对(0,0)进行翻转,则翻转后棋盘状态为n^51200(^表示异或),如果对(0,1)位置进行翻转,则与翻转棋盘0000 0000 0000 0000的(0,1)位置得到的十进制数(58368)异或即可,以此类推,这样就可以对二进制位表示棋盘进行翻转操作了。

代码

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <string>
using namespace std;

struct Node
{
int state;
int steps;

Node(){}
Node(int state, int steps):state(state), steps(steps){}
};

int flip[16];      //存储16中翻转状态
int visit[65536];  //记录棋盘状态是否被访问过
queue<Node> q;

void init() //初始化
{
memset(visit, 0, sizeof(visit));
while(!q.empty()) q.pop();

int dir[4][2]={ {1, 0}, {-1, 0}, {0, 1}, {0, -1}};
int temp;
for(int i=0; i<4; i++)  //计算翻转的16种状态
{
for(int j=0; j<4; j++)
{
temp = 0;
temp ^= (1<<((3-i)*4 + 3-j));
for(int k=0; k<4; k++)
{
int ni = i+dir[k][0];
int nj = j+dir[k][1];

if(ni>=0 && ni<4 && nj>=0 && nj<4)
temp ^= (1<<((3-ni)*4 + 3-nj));
}
flip[i*4+j] = temp;
}
}
}

int bfs()
{
while(!q.empty())
{
Node node = q.front();
q.pop();
if(node.state==0 || node.state==65535)
return node.steps;
for(int i=0; i<16; i++)
{
Node next;
next.state = node.state^flip[i];
next.steps = node.steps+1;
if(!visit[next.state])
{
visit[next.state] = 1;
q.push(next);
}
}
}
return -1;  // "Impossible"
}

int main()
{
//freopen("poj1753.txt", "r", stdin);
string s;
int state = 0;
for(int i=0; i<4; i++)
{
cin>>s;
for(int j=0; j<4; j++)
{
state = state<<1;
if(s[j]=='b')
state += 1;
}
}

init();
q.push(Node(state, 0));
visit[state] = 1;

int ans = bfs();
if(ans == -1)
cout<<"Impossible"<<endl;
else cout<<ans<<endl;
return 0;
}

参考

1、https://www.geek-share.com/detail/2543661562.html

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: