http://poj.org/problem?id=1753
题意:给一个只含‘b’和‘w’的4*4的棋盘,当翻一个格子时,它上下左右的格子也要翻转,问最少需要多少步使棋盘全是‘b’或‘w’。
因为棋盘4*4,共16个格子,每个格子用二进制0,1表示黑和白,整个棋盘共65535中状态。用x表示初始状态,然后枚举翻转每个格子,进行bfs。当状态为0或65535时表示说明全是‘b’或‘w’.
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <stack>
#include <vector>
#include <queue>
#define LL long long
#define _LL __int64
using namespace std;
struct node
{
int sta;
int step;
};
char map[4][4];
queue <node> que;
int vis[65536];
//当前状态是cur,计算当翻转第i个格子后的状态
int filp(int cur, int i)
{
cur = cur ^ (1<<i);
if(i > 3)
cur = cur ^ (1<<(i-4));
if(i < 12)
cur = cur ^ (1<<(i+4));
if(i%4 != 0)
cur = cur ^ (1<<(i-1));
if(i%4 != 3)
cur = cur ^ (1<<(i+1));
return cur;
}
void bfs(int x)
{
memset(vis,0,sizeof(vis));
while(!que.empty()) que.pop();
vis[x] = 1;
que.push((struct node){x,0});
while(!que.empty())
{
struct node u = que.front();
que.pop();
if(u.sta == 0 || u.sta == 65535)
{
printf("%d\n",u.step);
return;
}
for(int i = 0; i < 16; i++)
{
int tmp = filp(u.sta,i);
if(!vis[tmp])
{
vis[tmp] = 1;
que.push((struct node){tmp,u.step+1});
}
}
}
printf("Impossible\n");
}
int main()
{
int x;
x = 0;
for(int i = 0; i < 4; i++)
{
scanf("%s",map[i]);
for(int j = 0; j < 4; j++)
{
if(map[i][j] == 'w')
x <<= 1;
else
x = (x << 1) + 1;
}
}
bfs(x);
return 0;
}