思路:**枚举第一行的所有情况**(因为只看上下左右,所以第一行确定后,就可以确定剩余行的情况了QwQ)            
这里我们**采用x状压一下**,然后从小到达枚举x(即枚举把第一行的哪些0变成1),把修改过第一行的原数组存到b数组中(ps:要判断**有没有把1改成0**,改了则不行,跳过)。        
然后根据第一行确定要变化其他行的哪些数字,如果**存在需要把1改成0的情况,则此方案不行。**        
最后取每种情况的最小值就好啦~ 附上本蒟蒻的代码QWQ
```cpp
#include<bits/stdc++.h>
using namespace std;
int t,n,x,ans;
int a[20][20],b[20][20];//b存每种情况修改后的数组
int dx[3]={0,0,-1};
int dy[3]={1,-1,0};//上左右三个方向
int check(int m){//当第一行的情况为m时
	int num=0;//需要修改的次数
	for(int i=n;i>=1;i--){
		b[1][i]=m&1;
		m=m>>1;
		if(a[1][i]==0&&b[1][i]==1)
			num++;
		if(a[1][i]==1&&b[1][i]==0)//如果把1变为0了
			return 0x7fffffff;//此方案不行
	}
	for(int i=1;i<n;i++){
		for(int j=1;j<=n;j++){
			int sum=0;
			for(int k=0;k<3;k++){
				int xx=dx[k]+i;
				int yy=dy[k]+j;
				if(xx>0&&xx<=n&&yy>0&&yy<=n)
					sum+=b[xx][yy];			
			}
			if(sum%2==0&&b[i+1][j]==1) return 0x7fffffff;//三个方向
            和为偶数,下方数为0,不行
			if(sum%2==1&&b[i+1][j]==0) b[i+1][j]=1,num++;//0改1
		}
	}
	return num;
}
int main(){
	scanf("%d",&t);
	for(int cas=1;cas<=t;cas++){
		ans=0x7fffffff;
		scanf("%d",&n);
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
				scanf("%d",&a[i][j]);
		for(int i=1;i<=n;i++)		
			x+=x<<2+a[1][i];
		for(int i=x;i<(1<<n);i++){//枚举第一行
			for(int xx=1;xx<=n;xx++)
				for(int yy=1;yy<=n;yy++)
					b[xx][yy]=a[xx][yy];
			ans=min(ans,check(i));
		}	
		if(ans==0x7fffffff) printf("Case %d: -1\n",cas);
		else printf("Case %d: %d\n",cas,ans);
	}
	return 0;
}
```
原文:https://www.cnblogs.com/Johanna/p/12101284.html