题意:给出一个n*n的 0、1矩阵,把尽量少的0改成1,使得每个元素的上下左右的元素之和都为偶数。
思路:约束条件是某元素周围上下左右四个元素之和必须为偶数,那么,只需要枚举第一行,剩下的n-1行根据前一行递推出来。
话说最近改了一下代码风格,盗用了某大神的define和template。。。下面代码就不贴那部分了。
代码:
1 const int maxn = 20; 2 const int inf = 9999999; 3 int mi; 4 int n, a[maxn][maxn], b[maxn][maxn], c[maxn]; 5 6 int make(){ 7 int v; 8 REP(i, n) 9 b[0][i] = c[i]; 10 FOR(i, 1, n) 11 REP(j, n){ 12 v = b[i-2][j] + b[i-1][j-1] + b[i-1][j+1]; 13 b[i][j] = (v&1); 14 } 15 } 16 17 int cal(){ 18 int res = 0; 19 REP(i, n) 20 REP(j, n){ 21 if(a[i][j] == 1 && b[i][j] == 0)//和为偶数 22 return inf; 23 if(a[i][j] == 0 && b[i][j] == 1)//和为奇数 24 res++; 25 } 26 return res; 27 } 28 29 void solve(int s){ 30 if(s == n){ 31 make(); 32 checkmin(mi, cal()); 33 return ; 34 } 35 c[s] = 0; 36 solve(s + 1); 37 c[s] = 1; 38 solve(s + 1); 39 } 40 41 void init(){ 42 mi = inf; 43 memset(b, 0, sizeof(b)); 44 } 45 int main(){ 46 #ifndef ONLINE_JUDGE 47 freopen("in.txt", "r", stdin); 48 #endif 49 int t, k = 0; 50 cin>>t; 51 while(t--){ 52 init(); 53 k++; 54 cin>>n; 55 REP(i,n) 56 REP(j,n) 57 scanf("%d", &a[i][j]); 58 printf("Case %d: ", k); 59 solve(0); 60 if(mi == inf) puts("-1"); 61 else printf("%d\n",mi); 62 } 63 return 0; 64 }