POJ 3279 Fliptile 状态压缩,思路 难度:2
http://poj.org/problem?id=3279
明显,每一位上只需要是0或者1,
遍历第一行的所有取值可能,(1<<15,时间足够)对每种取值可能:
对于第0-n-2行,因为上一行和本身行都已确定,所以可以确定下一行
最后检查第n-1行是否满足条件即可
#include <cstdio> #include <cstring> #include <algorithm> #include <queue> using namespace std; int maz[15][15]; int op[15][15]; int ans[15][15],mn; int n,m; void getop(int sta){ memset(op,0,sizeof(op)); for(int i=0;i<n;i++){ if(sta&(1<<i)){ op[0][i]=1; } } } int getone(){ int num=0; for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ num+=op[i][j]; } } return num; } const int dx[4]={0,-1,0,0}; const int dy[4]={0,0,1,-1}; bool in(int x,int y){ return x>=0&&x<n&&y>=0&&y<m; } bool judge(int x,int y){ int num=maz[x][y]; for(int i=0;i<4;i++){ int tx=x+dx[i],ty=y+dy[i]; if(in(tx,ty))num+=op[tx][ty]; } return (num&1)==0; } int main(){ scanf("%d%d",&n,&m); for(int i=0;i<n;i++) for(int j=0;j<m;j++) scanf("%d",maz[i]+j); int mn=0x7ffffff; for(int sta=0;sta<(1<<n);sta++){ getop(sta); for(int i=0;i<n-1;i++){ for(int j=0;j<m;j++){ if(!judge(i,j)){ op[i+1][j]=1; } } } bool fl=true; for(int j=0;j<m;j++){ if(!judge(n-1,j)){ fl=false; break; } } if(fl){ int num=getone(); if(num<mn){ for(int i=0;i<n;i++){ copy(op[i],op[i]+m,ans[i]); } mn=num; } } } if(mn<=n*m) for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ printf("%d%c",ans[i][j],j==m-1?'\n':' '); } } else puts("IMPOSSIBLE"); return 0; }