算个水题吧,但是技巧很多。
像这种状态类似 0 1 的 可以尝试着用2进制来表示。
贴个代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int INF = 0x7fffffff;
int n,A[20][20],B[20][20];
int Check(int s) { //s 的用二进制表示第一行 0 1 状态.
memset(B,0,sizeof(B));
for(int c = 0; c < n; ++c) { //s为第一行的可能状态 。
if(s & (1<<c)) B[0][c] = 1;
else if(A[0][c] == 1) return INF;
}
for(int r = 1; r < n; ++r) {
for(int c = 0; c < n; ++c) {
int sum = 0;
if(r > 1) sum += B[r-2][c];
if(c > 0) sum += B[r-1][c-1];
if(c < n-1) sum += B[r-1][c+1];
B[r][c] = sum % 2; //计算B[r-1][c] 的四周数值.
if(A[r][c] == 1 && B[r][c] == 0) return INF;
}
}
int cnt = 0; //统计要改的0的数目.
for(int r = 0; r < n; ++r)
for(int c = 0; c < n; ++c)
if(A[r][c] != B[r][c]) cnt++;
return cnt;
}
int main() {
int T;
cin >> T;
for(int kase = 1; kase <= T; kase ++) {
cin >> n;
for(int i = 0; i < n; ++i)
for(int j = 0; j < n; ++j)
cin >> A[i][j];
int cnt = INF;
for(int s = 0; s < (1<<n); s++) {
cnt = min(cnt,Check(s));
}
if(cnt == INF) cnt = -1;
printf("Case %d: %d\n",kase,cnt);
}
return 0;
}