【枚举】POJ 3279

直达–>POJ 3279 Fliptile

题意:poj的奶牛又开始作孽了,这回他一跺脚就会让上下左右的砖块翻转(1->0 || 0->1),问你最少踩哪些砖块才能让初始的砖块全部变成0,要输出踩砖块位置。

思路:也不知道为什么归类在搜索里,问了大牛,枚举第一行的情况(1<

#include <cstdio>
#include <cstring>
using namespace std;
int N,M;
int maps[100][100];
int dx[]={1,-1,0,0,0};
int dy[]={0,0,-1,1,0};
int ans[100][100];
int flips[100][100];
int r;

int color(int x,int y){ //判断当前砖块是什么颜色
    int c = maps[x][y];
    for(int i=0;i<5;i++){
        int x1 = x+dx[i];
        int y1 = y+dy[i];
        if(x1<M&&y1<N&&x1>=0&&y1>=0)
            c+=flips[x1][y1];
    }
    return c%2;
}
int canl(){
    int res = 0;
    for(int i=1;i<M;i++){
        for(int j=0;j<N;j++){
            if(color(i-1,j)){//如果上一个前为1 则翻动此块
                flips[i][j] = 1;
            }
        }
    }
    for(int i=0; i<N; i++){//判断最后一行为不为全0
        if(color(M-1,i)){
            return -1;
        }
    }
    for(int i=0;i<M;i++){
        for(int j=0;j<N;j++){
            res+=flips[i][j];
        }
    }
    return res;
}
void solve(){
    for(int i=0;i<(1<<N);i++){ //枚举第一行所有情况
        memset(flips,0,sizeof(flips));

        for(int j=0;j<N;j++){
            flips[0][N-j-1] = i>>j&1; 
        }
        int num = canl();
        if(num >=0 && (r<0||num<r)){
            r = num;
            memcpy(ans,flips,sizeof(flips)); //求出最优解存入ans数组
        }
    }
    if(r==-1)
        printf("IMPOSSIBLE\n");
    else{
        for(int i=0; i<M; i++){
            for(int j=0; j<N-1; j++){
                printf("%d ",ans[i][j]);
            }
            printf("%d\n",ans[i][N-1]);
        }
    }
}
void init()
{
    memset(maps,0,sizeof(maps));
    memset(ans,0,sizeof(ans));
}
int main()
{
    while(~scanf("%d%d",&M,&N)){
        r = -1;
        init();
        for(int i=0;i<M;i++){
            for(int j=0;j<N;j++){
                scanf("%d",&maps[i][j]);
            }
        }
        solve();
    }
    return 0;
}
posted @ 2016-08-21 15:16  霜降sma  阅读(141)  评论(0编辑  收藏  举报