毫无疑问,这道题需要枚举。并且,如果其他三行(三列)都已如题所述的弄好,那么,最后一行(一列)如果还不好,就无解。从上往下一行一行的看,假如第一行没有全白(全黑),那么可以通过第二行的翻转来改变第一行使其全白(全黑),第三行同理,只有第四行剩下,所以,可以通过检测第四行是否全白(全黑)来检验这种翻转方法是否可行。同时,正因此,第一行如何翻转决定了以后的走向。所以,可以通过01串(转化成十进制数字更好一点)来枚举表达第一行的翻转情况,之后的行通过弥补之前行的差错来进行翻转。这样就大功告成了!对了,别忘了有全白全黑两种情况的。
剩下的部分可以看代码注释
#include <iostream>
#include <algorithm>
using namespace std;
char ch[4][4]; //接受到的字符
bool th_b[4][4]; //用01表示黑白两种状态, 这个表示全黑
bool th_w[4][4]; //这个表示全白
void flip(bool(*th)[4], int row, int col) //反转黑白
{
th[row][col] = !th[row][col];
}
void read(char(*a)[4], bool(*b)[4], bool(*c)[4]) //读入字符,转化成01
{
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 4; ++j)
{
if (a[i][j] == 'w')
b[i][j] = c[i][j] = 0;
else
b[i][j] = c[i][j] = 1;
}
}
}
int solve_b(bool(*th)[4]) 全白情况
{
int count = 0;
for (int row = 1; row < 4; ++row)
{
for (int col = 0; col < 4; ++col)
{
if (!th[row - 1][col]) //0表示白
{
++count;
flip(th, row, col);
flip(th, row - 1, col);
if (row + 1 <= 3) //下边
flip(th, row + 1, col);
if (col + 1 <= 3) //右边
flip(th, row, col + 1);
if (col - 1 >= 0) //左边
flip(th, row, col - 1);
}
}
}
int ss = 0;
for (int i = 0; i < 4; ++i)
ss += th[3][i];
if (ss == 4)
return count;
else
return 0;
}
int solve_w(bool(*th)[4]) //全黑情况
{
int count = 0;
for (int row = 1; row < 4; ++row)
{
for (int col = 0; col < 4; ++col)
{
if (th[row - 1][col]) //1表示黑
{
++count;
flip(th, row, col);
flip(th, row - 1, col);
if (row + 1 <= 3)
flip(th, row + 1, col);
if (col + 1 <= 3)
flip(th, row, col + 1);
if (col - 1 >= 0)
flip(th, row, col - 1);
}
}
}
int ss = 0;
for (int i = 0; i < 4; ++i)
ss += th[3][i];
if (ss == 0)
return count;
else
return 0;
}
int toByte(bool (*th_b)[4], bool (*th_w)[4], int num)
{
int _ans = 0;
for (int i = 0; i < 4; ++i)
{
if ((num >> i) & 0x1) //对第一行的翻转
{
flip(th_b, 0, i);
flip(th_b, 1, i);
flip(th_w, 0, i);
flip(th_w, 1, i);
if (i + 1 < 4)
{
flip(th_w, 0, i + 1);
flip(th_b, 0, i + 1);
}
if (i - 1 >= 0)
{
flip(th_w, 0, i - 1);
flip(th_b, 0, i - 1);
}
++_ans;
}
}
return _ans;
}
int main(void)
{
for (int i = 0; i < 4; ++i)
cin >> ch[i];
int ans = 0x7f7f7f7f, s(0);
read(ch, th_w, th_b);
for (int i = 0; i < 4; ++i)
for (int j = 0; j < 4; ++j)
s += th_w[i][j];
if (s == 0 || s == 16) //特殊情况
{
cout << 0 << endl;
return 0;
}
for (int i = 0; i < 16; ++i)
{
read(ch, th_w, th_b);
int sum1 = toByte(th_w, th_b, i), sum = 0, b = 0x7f7f, a = 0x7f7f;
int sum_w = solve_w(th_w);
int sum_b = solve_b(th_b);
if (sum_w)
a = sum1 + sum_w;
if (sum_b)
b = sum1 + sum_b;
if (a == 0x7f7f && b == 0x7f7f)
continue;
sum = min(a, b);
ans = min(ans, sum);
}
if (ans < 0x7f7f7f7f)
cout << ans << endl;
else
cout << "Impossible" << endl;
return 0;
}
唉,这个题我之前在写第一行的时候忘了上下左右了,害的我迷茫了好久

京公网安备 11010502036488号