类似于反转问题,枚举第一行即可。
#include <cstdio>
#include <cstring>
#include <algorithm>
const int maxn = 20;
const int inf = 400;
int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, -1, 0, 1};
int grid[maxn][maxn];
int flip[maxn][maxn];
int n;
bool get(int x, int y) {
int c = 0;
for (int i = 0; i < 4; i++) {
int nx = x + dx[i];
int ny = y + dy[i];
if (nx >= 0 && nx < n && ny >= 0 && ny < n) {
c += grid[nx][ny] + flip[nx][ny];
}
}
return c & 1;
}
int main(int argc, char const *argv[]) {
int T;
scanf("%d", &T);
for (int t = 1; t <= T; t++) {
scanf("%d", &n);
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
scanf("%d", &grid[i][j]);
}
}
int ans = inf;
for (int i = 0; i < (1 << n); i++) {
bool ok = true;
memset(flip, 0, sizeof(flip));
for (int j = 0; j < n; j++) {
flip[0][n-j-1] = (i >> j) & 1;
if (grid[0][n-j-1] && flip[0][n-j-1]) {
ok = false;
break;
}
}
if (!ok) {
continue;
}
for (int j = 1; j < n; j++) {
for (int k = 0; k < n; k++) {
if (get(j - 1, k)) {
if (grid[j][k]) {
ok = false;
break;
}
flip[j][k] = 1;
}
}
if (!ok) {
break;
}
}
if (!ok) {
continue;
}
for (int j = 0; j < n; j++) {
if (get(n - 1, j)) {
ok = false;
break;
}
}
if (!ok) {
continue;
}
int tmp = 0;
for (int j = 0; j < n; j++) {
for (int k = 0; k < n; k++) {
tmp += flip[j][k];
}
}
ans = std::min(ans, tmp);
}
printf("Case %d: ", t);
if (ans == inf) {
puts("-1");
} else {
printf("%d\n", ans);
}
}
return 0;
}