Poj 3279 Fliptile

来源:互联网 发布:遥感集市 免费数据 编辑:程序博客网 时间:2024/04/27 13:40

题目的意思大概是这样的:


给你一个n*m的图,把图中所有的1变成0,每次你可以选择一个“十”字型范围进行反转(0变1 ,1变0),



1 1 1

1 1 1

1 1 1

在中间位置翻转一次会变成

1 0 1

0 0 0

1 0 1


问你最少需要多少次才能完成,并输出最少翻转的位置,(多组输出字典序)

思路:

如果直接尝试枚举每个位置的翻转,那么需要复杂度为O2^(m*n),过不去的,但是仔细思考后你会发现,如果第一行的翻转是指定的话,那么这个图能不能被全部反转为0就已经确定了。

因此,思路为:枚举第0行的所有翻转方式,然后从第1行开始,若某个点上方那个点需要被反转则反转这个点,同时记录反转过程中反转最少的一次即可



代码如下:

#include <stdio.h>#include <algorithm>#include <iostream>#include <cstring>using namespace std;int n,m,Map[20][20],temp[20][20];//Map用来保存初始状态,temp用来保存枚举第一行反转形式后的状态int current[20][20],ans[20][20];//current用来枚举第一行反转形式后反转的位置,ans用来储存答案(最少反转策略)void change(int x,int y){//反转这个点和它挨着的四个点    temp[x][y]=!temp[x][y];    if(x-1>=0)temp[x-1][y]=!temp[x-1][y];    if(x+1<n)temp[x+1][y]=!temp[x+1][y];    if(y-1>=0)temp[x][y-1]=!temp[x][y-1];    if(y+1<m)temp[x][y+1]=!temp[x][y+1];}int solve(){    int ok=1000;    for(int k=0;k<(1<<m);k++){        //printf("* * * %d\n",k);        for(int i=0;i<n;i++)for(int j=0;j<m;j++)temp[i][j]=Map[i][j];        memset(current,0,sizeof(current));        int Max=0;        for(int j=0;j<m;j++){            current[0][(m-1)-j]=(k>>j)&1;            if(current[0][(m-1)-j]){                Max++;                change(0,(m-1)-j);            }        }        for(int i=1;i<n;i++){            for(int j=0;j<m;j++){                if(temp[i-1][j]){                    Max++;                    change(i,j);                    current[i][j]=1;                }            }        }        int t;        /*for(int i=0;i<n;i++){            for(int j=0;j<m;j++)printf("%d ",current[i][j]);            printf("\n");        }        printf("\n");*/        for(t=0;t<m;t++)if(temp[n-1][t])break;        if(t==m && ok>Max){            ok=Max;            for(int i=0;i<n;i++){                for(int j=0;j<m;j++)ans[i][j]=current[i][j];            }        }    }    if(ok==1000)return false;    return true;}int main(){    scanf("%d%d",&n,&m);    for(int i=0;i<n;i++){        for(int j=0;j<m;j++)scanf("%d",&Map[i][j]);    }    if(solve()){        for(int i=0;i<n;i++){            for(int j=0;j<m;j++)printf("%d ",ans[i][j]);            printf("\n");        }    }    else printf("IMPOSSIBLE\n");}



0 0