题目链接:POJ 1753 Flip Game
把每个局面看成一个状态,那么共有1 << 16种状态。使用二进制来表示每个状态,这也应该算是一种hash吧,翻转的的话让这一位与1相异或。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
struct State
{
int s, dis;
State(int s = 0, int dis = 0) : s(s), dis(dis) {};
};
const int MAX_S = (1 << 16) + 100;
const int MAX_N = 4 + 2;
const int INF = (1 << 29);
int vis[MAX_S];
int _end1 = (1 << 16) - 1, _end2 = 0, res = INF, _start = 0;
char _map[MAX_N][MAX_N];
queue <State> Q;
void BFS()
{
State a;
int ds;
while(!Q.empty())
{
a = Q.front();
Q.pop();
for(int i = 0; i < 4; i++)
{
for(int j = 0; j < 4; j++)
{
ds = a.s ^ (1 << (4 * i + j)); // 选中位置
if(i != 0)
ds = ds ^ (1 << (4 * (i - 1) + j)); // 选中位置的上方
if(j != 0)
ds = ds ^ (1 << (4 * i + j - 1)); // 选中位置的左侧
if(i != 3)
ds = ds ^ (1 << (4 * (i + 1) + j)); // 选中位置的下方
if(j != 3)
ds = ds ^ (1 << (4 * i + j + 1)); // 选中位置的右侧
if(!vis[ds])
{
if(ds == _end1 || ds == _end2)
{
res = a.dis + 1;
return ;
}
Q.push(State(ds, a.dis + 1));
vis[ds] = 1;
}
}
}
}
}
int main()
{
memset(vis, 0, sizeof(vis));
for(int i = 0; i < 4; i++)
{
scanf("%s", _map[i]);
for(int j = 0; j < 4; j++)
{
// b = 1, w = 0
if(_map[i][j] == 'b')
_start = (_start << 1) + 1;
else
_start = _start << 1;
}
}
if(_start == _end1 || _start == _end2)
{
printf("0\n");
return 0;
}
Q.push(State(_start, 0));
vis[_start] = 1;
BFS();
if(res == INF)
printf("Impossible\n");
else
printf("%d\n", res);
return 0;
}