CH0201 奇怪的开关 【二进制,枚举】
当上一行的开关方法确定时,如果上一行灯是关的,本行同列的灯就要打开,如果上一行灯是开的,本行同列的灯就不能打开。先确定第一行,剩下的方法唯一。
#include <bits/stdc++.h>
using namespace std;
const int N = 5 + 5;
const int INF = 0x3f3f3f3f;
int T, n = 5, G[N][N], turn[N][N];
bool in_map (int x, int y) {
return 1 <= x && x <= 5 && 1 <= y && y <= 5;
}
int sumX (int x, int y) {
int ret = G[x][y] ^ turn[x][y];
if (in_map (x - 1, y)) ret ^= turn[x - 1][y];
if (in_map (x, y - 1)) ret ^= turn[x][y - 1];
if (in_map (x, y + 1)) ret ^= turn[x][y + 1];
return ret;
}
bool can_use (int fst) {
// if (fst == 16) cout << "fst = " << fst << endl;
memset (turn, 0, sizeof (turn));
for (int i = 1; i <= 5; ++i) {
turn[1][i] = (fst >> (i - 1)) & 1;
// if (fst == 16) cout << "turn[1][" << i << "] = " << turn[1][i] << endl;
}
for (int i = 2; i <= 5; ++i) {
for (int j = 1; j <= 5; ++j) {
// if (fst == 16) {
// cout << "i = " << i << ", j = " << j << ", sumX = " << sumX(i - 1, j) << endl;
// }
if (sumX (i - 1, j) == 0) {
turn[i][j] = 1;
}
}
}
for (int i = 1; i <= 5; ++i) {
if (sumX (5, i) == 0) return false;
}
return true;
}
int get_ans () {
int ret = 0;
for (int i = 1; i <= 5; ++i) {
for (int j = 1; j <= 5; ++j) {
ret += turn[i][j];
}
}
return ret;
}
int solve () {
int ret = INF;
for (int i = 0; i < 1 << 5; ++i) {
if (can_use (i)) {
// cout << "can_use" << endl;
ret = min (ret, get_ans ());
}
}
// cout << "ret = " << ret << endl;
return ret > 6 ? -1 : ret;
}
int main () {
freopen ("data.in", "r", stdin);
// freopen ("data.out", "w", stdout);
cin >> T;
while (T--) {
for (int i = 1; i <= 5; ++i) {
for (int j = 1; j <= 5; ++j) {
char _ch;
scanf (" %c", &_ch);
G[i][j] = (int)_ch - (int)'0';
}
}
cout << solve () << endl;
}
}