状态压缩+枚举 UVA 11464 Even Parity

题目传送门

 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 }
编译人生,运行世界!
原文地址:https://www.cnblogs.com/Running-Time/p/4658730.html