题目大意:有一个N*N的01矩阵,你的任务是把尽量少的0变成1,(但不能将1变成0)以使得每个元素的上下左右的元素(若存在)均为偶数。
思路 : 如果暴力枚举每一个位置的话时间复杂度为 2 的255 次方,肯定不行 。但是如果只枚举第一行,其他下面几行都能够通过
上边的来固定是0还是1。时间复杂度就是 2的15次方 加2的n次方;
利用而二进制数来枚举每一种情况 00000 00000 00000 ~11111 11111 11111 (1<<15)
#include <iostream>
#include <cstring>
using namespace std;
int arr[16][16],brr[16][16];
const int inf=1e9+7;
int n;
int change(int s)
{
memset(brr,0,sizeof(brr)); //不要忘了更新数组
for(int i=0; i<n; i++)
{
if(s&(1<<i)) brr[0][i]=1; //给第一行brr赋值,实际上是brr[][]的01顺序是的S的01
//相反的
else if(arr[0][i]==1) return inf; //1不能变成0
}
for(int i=1;i<n;i++)
for(int j=0;j<n;j++)
{
int sum=0;
if(i>1) sum+=brr[i-2][j];
if(j>0) sum+=brr[i-1][j-1];
if(j<n) sum+=brr[i-1][j+1];
brr[i][j]=sum%2; //确定下一位是0 还是1
if(brr[i][j]==0&&arr[i][j]==1) return inf;
}
int cnt=0;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
if(brr[i][j]!=arr[i][j])
cnt++;
}
return cnt;
}
int main()
{
int T;
cin >>T;
for(int t=1; t<=T; t++)
{
cin >>n;
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
cin >>arr[i][j];
int ans=inf;
for(int i=0; i<(1<<n); i++)
{
int k=change(i);
if(ans>k)
ans=k;
}
if(ans!=inf)
cout <<"Case "<<t<<": "<<ans<<endl;
else
cout <<"Case "<<t<<": "<<-1<<endl;
}
return 0;
}