链接:
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2459
思路:
这题因为题目没理解好,以为是要让每个格子周围的九个数字之和为偶数。。。导致了想了好久没想出。后来才发现原来只是上,下,左,右...
其实就是暴力穷举,枚举第一行可以变化的情况,然后根据第一行依次求出后面行的情况。注意1不能变为0.
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int INF = 0x3f3f3f; const int maxn = 20; int n; int mat[maxn][maxn]; int B[maxn][maxn]; int check(int s){ memset(B, 0, sizeof(B)); for(int i=1; i<=n; ++i){ if(s & (1<<(i-1))) B[1][i]=1; else if(mat[1][i]) return INF; } for(int i=2; i<=n; ++i){ for(int j=1; j<=n; ++j){ int sum = B[i-2][j]+B[i-1][j-1]+B[i-1][j+1]; B[i][j] = sum&1; if(mat[i][j] && B[i][j]==0) return INF; } } int cnt=0; for(int i=1; i<=n; ++i) for(int j=1; j<=n; ++j) if(mat[i][j] !=B[i][j]) ++cnt; return cnt; } int main(){ int T; scanf("%d", &T); memset(mat, 0, sizeof(mat)); for(int cas=1; cas<=T; ++cas){ scanf("%d", &n); for(int i=1; i<=n; ++i) for(int j=1; j<=n; ++j) scanf("%d",&mat[i][j]); int ans = INF; for(int s=0; s<(1<<n); ++s) ans = min(ans, check(s)); if(ans == INF) ans=-1; printf("Case %d: %d\n", cas, ans); } return 0; }