算是一类的题目 zoj也看到过 今天终于写了
给你一个0 1 的矩阵 可以把0变成1 1 不能变成0 然后最小的变换次数是每一个位置的上下左右加起来的和是偶数
枚举第一行 根据第一行下面的都已经确定了 O(2^n*N*N)
#include <stdio.h> #include <string.h> const int MAX = 20; int n; int min; int a[MAX][MAX]; int b[MAX][MAX]; int check() { int i,j,sum,cnt = 0; for(i = 0;i < n; i++) { if(a[0][i] == 1 && b[0][i] == 0) { return 0x7ffffff; } else if(a[0][i] != b[0][i]) cnt++; } for(i = 1; i < n; i++) { for(j = 0; j < n; j++) { sum = 0; if(i > 1) sum += b[i-2][j]; if(j > 0) sum += b[i-1][j-1]; if(j < n - 1) sum += b[i-1][j+1]; b[i][j] = sum % 2; if(a[i][j] == 1 && b[i][j] == 0) return 0x7ffffff; else if(a[i][j] != b[i][j]) cnt++; } } return cnt; } void dfs(int k) { if(k == n) { int res = check(); if(min > res) min = res; return; } b[0][k] = 0; dfs(k+1); b[0][k] = 1; dfs(k+1); } int main() { int t,i,j,cas = 1; scanf("%d",&t); while(t--) { scanf("%d",&n); for(i = 0; i < n; i++) for(j = 0; j < n; j++) scanf("%d",&a[i][j]); min = 0x7ffffff; dfs(0); printf("Case %d: ",cas++); if(min == 0x7ffffff) puts("-1"); else printf("%d\n",min); } return 0; }