題意:有一個n*n的01矩陣,任務是把盡可能少的0變成1,使得每個元素的上、下、左、右元素之和為偶數。
思路:很容易想到的思路是枚舉每個點是0還是1,因為n<=15,復雜度就是2^225顯然TLE。注意到每次確定一樣以後,下一行就是可以被確定的!所以,只要枚舉第一行的狀態,就可以推出每一行的狀態,復雜度是15*2^15
#include<cstdio> #include<iostream> #define INF 0x3f3f3f3f #define MAXN 20 using namespace std; int n,ori[MAXN][MAXN],t[MAXN][MAXN],dx[]={0,0,-1},dy[]={1,-1,0},ans,ca=0,T; bool f(int x,int y) { int sum=0; for(int i=0;i<3;++i) if(x+dx[i]>=0 && y+dy[i]>=0 && x+dx[i]<n && y+dy[i]<n) sum+=t[x+dx[i]][y+dy[i]]; return sum&1; } bool generate(int x,int &sum)//x>0 { for(int i=0;i<n;++i) if(f(x-1,i)) { t[x][i]=1; if(!ori[x][i]) ++sum; } else { if(ori[x][i]) {sum=INF;return 0;} t[x][i]=0; } return 1; } int solve(int pre) { int sum=pre; for(int i=1;i<n;++i) if(!generate(i,sum)) break; return sum; } void dfs(int pos,int step) { if(pos>=n) {ans=min(ans,solve(step));return;} if(ori[0][pos]) {t[0][pos]=1;dfs(pos+1,step);} else { t[0][pos]=0; dfs(pos+1,step); t[0][pos]=1; dfs(pos+1,step+1); } } int main() { scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=0;i<n;++i) for(int j=0;j<n;++j) scanf("%d",&ori[i][j]); ans=INF; dfs(0,0); printf("Case %d: %d\n",++ca,ans>=INF? -1:ans); } return 0; }