这是我第一篇博客,虽说是原创,但是是借着讲课时的PPT的思路敲的。如有雷同,不胜荣幸。
题目大意:有4*4的正方形,每个格子要么是黑色,要么是白色,当把一个格子的颜色改变(黑->白或者白->黑)时,其周围上下左右(如果存在的话)的格子的颜色也被反转,问至少反转几个格子可以使4*4的正方形变为纯白或者纯黑
思路:1、一共16个棋子最多翻转16次,翻两次和不翻是一样的;
2、本题是求最小的步数所以用很标准的BFS那一套做就可以了,关键是状态的表示,算是加强了对BFS的印象
3、而本题可以用二进制来表示2^16个状态,然后多有的操作用位运算来完成,
右数第k位取反 x ^ (1 << k),注意从第0位开始
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <set>
#include <vector>
using namespace std;
int vis[1<<16];
struct node {
int val;
int step;
};
int sta;
int bfs()
{
queue<node> q;
node t;
t.step = 0;
t.val = sta;
q.push(t);
vis[sta] = 1;
while (!q.empty()) {
node t = q.front();
q.pop();
if (t.val == 0 || (t.val == (1<<16) -1)) {
cout << t.step << endl;
return 1;
}
if (t.step >= 16) continue;
for (int i = 0; i < 16; i++) {
node tmp = t;
tmp.step ++;
tmp.val = tmp.val ^ (1<<(i));
if (i%4 != 0) tmp.val = tmp.val ^ (1<<(i-1));
if ((i+1)%4 != 0) tmp.val = tmp.val ^ (1<<(i+1));
if (i > 3) tmp.val = tmp.val ^ (1<<(i-4));
if (i < 12) tmp.val = tmp.val ^ (1<<(i+4));
if (!vis[tmp.val]) {
q.push(tmp);
vis[tmp.val] = 1;
}
}
}
return -1;
}
int main()
{
char ch;
sta = 0;
scanf(" %c", &ch);
if (ch == 'b') sta = 1;
else sta = 0;
for (int i =1; i < 16; i++) {
scanf(" %c", &ch);
if (ch == 'b') sta = (sta<<1)|1;
else sta <<= 1;
}
memset(vis, 0,sizeof(vis));
int ans = bfs();
if (ans <= 0)puts("Impossible");
return 0;
}