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;
}
POJ 3279 Fliptile 状态压缩,思路 难度:2
原文:http://www.cnblogs.com/xuesu/p/4337449.html