枚举第一行的所有可能的情况,然后推出后面的n-1行,每推导出一个矩阵就和原来的矩阵比对,出现矛盾或者新的矩阵不满足题目的要求,就舍弃新矩阵,否则就统计0变成1的位置的个数,找到所有的个数的最小值就行了。
#include <stdio.h>
#define INF 0x7fffffff
unsigned char arr[20][20];
unsigned char arr_try[20][20];
void func(int n){
int i, j, k, min;
int sum, num, first_line, count;
bool right;
static int case_n = 1;
for(j=0; j<=n+1; j++) arr[n+1][j] = 0;
for(i=0; i<=n+1; i++) arr[i][n+1] = 0;
right = true;
for(i=1; i<=n; i++){
for(j=1; j<=n; j++){
sum = arr[i-1][j] + arr[i+1][j] + arr[i][j-1] + arr[i][j+1];
if(sum % 2){
right = false;
goto L1;
}
}
}
L1:
if(right){
printf("Case %d: 0\n", case_n++);
return;
}
for(j=0; j<=n+1; j++) arr_try[n+1][j] = 0;
for(i=0; i<=n+1; i++) arr_try[i][n+1] = 0;
num = 1;
for(i=2; i<=n; i++)
num = (num<<1) + 1;
min = INF;
for(k=0; k<=num; k++){
first_line = k;
for(j=1; j<=n; j++){
arr_try[1][j] = first_line & 1;
first_line >>= 1;
}
for(i=2; i<=n; i++){
for(j=1; j<=n; j++){
sum = arr_try[i-2][j] + arr_try[i-1][j-1] + arr_try[i-1][j+1];
if(sum % 2)
arr_try[i][j] = 1;
else
arr_try[i][j] = 0;
}
}
right = true;
for(i=1; i<=n; i++){
for(j=1; j<=n; j++){
sum = arr_try[i-1][j] + arr_try[i+1][j] + arr_try[i][j-1] + arr_try[i][j+1];
if(sum % 2){
right = false;
goto L2;
}
}
}
L2:
if(right){
count = 0;
for(i=1; i<=n; i++){
for(j=1; j<=n; j++){
if(arr[i][j]==0 && arr_try[i][j]==1)
count++;
if(arr[i][j]==1 && arr_try[i][j]==0){
right = false;
goto L3;
}
}
}
}
L3:
if(right){
if(count < min)
min = count;
}
}
if(INF == min){
printf("Case %d: -1\n", case_n++);
}
else{
printf("Case %d: %d\n", case_n++, min);
}
}
int main(void){
int case_n, n, i, j;
//freopen("input.dat", "r", stdin);
scanf("%d", &case_n);
while(case_n--){
scanf("%d", &n);
for(i=1; i<=n; i++){
for(j=1; j<=n; j++)
scanf("%d", arr[i]+j);
}
func(n);
}
return 0;
}