毫无疑问,这道题需要枚举。并且,如果其他三行(三列)都已如题所述的弄好,那么,最后一行(一列)如果还不好,就无解。从上往下一行一行的看,假如第一行没有全白(全黑),那么可以通过第二行的翻转来改变第一行使其全白(全黑),第三行同理,只有第四行剩下,所以,可以通过检测第四行是否全白(全黑)来检验这种翻转方法是否可行。同时,正因此,第一行如何翻转决定了以后的走向。所以,可以通过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; }
唉,这个题我之前在写第一行的时候忘了上下左右了,害的我迷茫了好久