题意:翻棋子,当出现全黑或是全白的时候停止,每次翻转连带着上、下、左、右一块翻转(如果有的话)。问实现全白或是全黑所需最少步数
思路:重点。。。。每个棋子被翻1,3,5,7或2,4,6,8次的效果完全一样。。。。所以,只要对所有棋子考虑翻或者不翻就可以了。总共2^16种状态,强行DFS........GG
然后考虑棋盘每行都可以用一个二进制串来表示,即用int的前4位来表示。
异或的性质:如1000与一个二进制串异或,二进制串的前三位不变,第四位反号(异或0不变,异或1反号)
#include<iostream>
#include<vector>
#include<string>
#include<queue>
/**
* @note 题意:翻棋子,当出现全黑或是全白的时候停止,每次翻转连带着上、下、左、右一块翻转(如果有的话)。问实现全白或是全黑所需最少步数
思路:重点。。。。每个棋子被翻1,3,5,7或2,4,6,8次的效果完全一样。。。。所以,只要对所有棋子考虑翻或者不翻就可以了。总共2^16种状态,强行DFS。。。GG
然后考虑棋盘每行都可以用一个二进制串来表示,即用int的前4位来表示。
异或的性质:如1000与一个二进制串异或,二进制串的前三位不变,第四位反号(异或0不变,异或1反号)
*/
using namespace std;
int field[6] = { 0 };
int state[][4] = { { 8,4,2,1 },{ 12,14,7,3 } };
///读取数据 用int中的前四位来表示棋盘的一行,1表示黑棋
void read()
{
for (int i = 1; i <= 4; i++)
{
for (int j = 1; j <= 4; j++)
{
field[i] <<= 1;
char temp;
cin >> temp;
if (temp=='b')
{
field[i] |= 1;
}
}
}
}
///反转
void flip(int i, int j)
{
--j;
field[i - 1] ^= state[0][j];
field[i] ^= state[1][j];
field[i + 1] ^= state[0][j];
}
///判断是否整个棋盘为同一色
bool check()
{
return (field[1] == 0 || field[1] == 15)
&& field[1] == field[2]
&& field[2] == field[3]
&& field[3] == field[4];
}
bool find(int n, int i, int j)
{
if (n == 0)
{
return check();
}
j++;
if (j > 4)
{
i += 1, j = 1;
}
if (i > 4)
{
return false;
}
for (; i <= 4; i++)
{
for (; j <= 4; j++)
{
flip(i, j);
if (find(n - 1, i, j))
{
return true;
}
flip(i, j);
}
j = 1;
}
return false;
}
void work()
{
for (int i = 0; i <= 16; i++)
{
if (find(i, 1, 0))
{
cout << i << endl;
return;
}
}
cout << "Impossible" << endl;
}
int main()
{
read();
work();
system("pause");
return 0;
}