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;
}

  

posted @ 2015-03-14 13:55  雪溯  阅读(148)  评论(0编辑  收藏  举报