题目传送门
1 /*
2 题意:求最少改变多少个0成1,使得每一个元素四周的和为偶数
3 状态压缩+枚举:枚举第一行的所有可能(1<<n),下一行完全能够由上一行递推出来,b数组保存该位置需要填什么
4 最后检查不同的数量,取最小值
5 */
6 #include <cstdio>
7 #include <algorithm>
8 #include <cstring>
9 using namespace std;
10
11 const int MAXN = 20;
12 const int INF = 0x3f3f3f3f;
13 int a[MAXN][MAXN], b[MAXN][MAXN];
14 int n;
15
16 int check(int s) {
17 memset (b, 0, sizeof (b));
18 for (int i=0; i<n; ++i) {
19 if (s & (1 << i)) b[0][i] = 1;
20 else if (a[0][i] == 1) return INF;
21 }
22
23 for (int i=1; i<n; ++i) {
24 for (int j=0; j<n; ++j) {
25 int sum = 0;
26 if (i > 1) sum += b[i-2][j];
27 if (j > 0) sum += b[i-1][j-1];
28 if (j < n-1) sum += b[i-1][j+1];
29 b[i][j] = sum % 2;
30 if (a[i][j] == 1 && b[i][j] == 0) return INF;
31 }
32 }
33
34 int ret = 0;
35 for (int i=0; i<n; ++i) {
36 for (int j=0; j<n; ++j) {
37 if (a[i][j] != b[i][j]) ret++;
38 }
39 }
40
41 return ret;
42 }
43
44 int main(void) { //UVA 11464 Even Parity
45 //freopen ("G.in", "r", stdin);
46
47 int t, cas = 0; scanf ("%d", &t);
48 while (t--) {
49 scanf ("%d", &n);
50 for (int i=0; i<n; ++i) {
51 for (int j=0; j<n; ++j) {
52 scanf ("%d", &a[i][j]);
53 }
54 }
55
56 int ans = INF;
57 for (int i=0; i<(1<<n); ++i) {
58 ans = min (ans, check (i));
59 }
60
61 if (ans == INF) ans = -1;
62 printf ("Case %d: %d
", ++cas, ans);
63 }
64
65 return 0;
66 }