题目大意:
有4*4的正方形,每个格子要么是黑色,要么是白色,当把一个格子的颜色改变(黑->白或者白->黑)时,其周围上下左右(如果存在的话)的格子的颜色也被反转,问至少反转几个格子可以使4*4的正方形变为纯白或者纯黑?
思路:位图 + BFS遍历
4*4的棋盘可以看成一个16位的二进制数,白色则该位等于1,黑色则该位为0。
之后根据题意对各个情况模拟,之后进行BFS搜索,结果为0或65535时结束搜索。
代码:
#include<iostream>
#include<Cstdio>
#include<Cstring>
#include<queue>
#define N 1<<16
using namespace std;
int mark[N], n;
int p[20] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192,
16384, 32768, 65536, 131072};
struct node
{
int x, step;
};
int bfs()
{
node cur, next;
queue<node>q;
if(n == 0 || n == 65535)
return 0;
cur.x = n;
cur.step = 0;
q.push(cur);
mark[n] = 1;
while(!q.empty())
{
cur = q.front();
q.pop();
for(int i = 0; i < 16; ++i)
{
next.x = cur.x;
next.x = cur.x^p[i];
if(i + 4 < 16)
next.x ^= p[i+4];
if(i - 4 >= 0)
next.x ^= p[i-4];
if(i % 4 < 3)
next.x ^= p[i + 1];
if(i % 4 > 0)
next.x ^= p[i - 1];
if(next.x == 0 || next.x == 65535)
return cur.step + 1;
if(mark[next.x] != 1)
{
next.step = cur.step + 1;
mark[next.x] = 1;
q.push(next);
}
}
}
return -1;
}
int main()
{
int i, j, temp;
char c;
n = 0;
for(i = 0; i < 4; i++)
{
for(j = 0; j < 4; j++)
{
scanf("%c", &c);
temp = i * 4 + j;
if(c=='b')
n = n + (1 << temp);
}
getchar();
}
i=bfs();
if(i==-1)
printf("Impossible\n");
else
printf("%d\n",i);
return 0;
}