题意:给了一个n*n的矩阵,矩阵元素不是0就是1,需要把尽量少的0变为1,使每个元素的上下左右和为偶数,问改变的元素的个数,如果无解输出-1。
题解:因为直接全部枚举会超时,可以考虑只枚举一行的,然后剩下的根据元素周围和是偶数的条件计算出来,然后找出最少改变的数量。
#include <stdio.h>
#include <string.h>
const int N = 20;
const int INF = 0x3f3f3f3f;
int n, g[N][N], arr[N][N];
int solve(int s) {
memset(arr, 0, sizeof(arr));
for (int i = 0; i < n; i++)
if (s & (1 << i))
arr[0][i] = 1;
else if (g[0][i])
return INF;
for (int i = 1; i < n; i++)
for (int j = 0; j < n; j++) {
int temp = 0;
if (i > 1)
temp += arr[i - 2][j];
if (j > 0)
temp += arr[i - 1][j - 1];
if (j < n - 1)
temp += arr[i - 1][j + 1];
arr[i][j] = temp % 2;
if (arr[i][j] == 0 && g[i][j] == 1)
return INF;
}
int k = 0;
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
if (g[i][j] != arr[i][j])
k++;
return k;
}
int main() {
int t, cas = 1;
scanf("%d", &t);
while (t--) {
scanf("%d", &n);
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
scanf("%d", &g[i][j]);
int minn = INF;
for (int i = 0; i < (1 << n); i++) {
int temp = solve(i);
if (minn > temp)
minn = temp;
}
if (minn == INF)
minn = -1;
printf("Case %d: %d\n", cas++, minn);
}
return 0;
}