poj3279 Fliptile(反转(开关问题))

题目链接:点击打开链接

题意描述:给定一个m*n的格子,每个格子要么为黑,要么为白,我们可以通过反转格子使颜色变为相反的颜色,反转x,y时,顺便会把相邻的四个格子的颜色改变,问最少需要反转多少次能使所有格子变为白色,并输出反转情况?


解题思路:典型的反转(开关问题)

分析:枚举第一行的所有情况,对于第一行已经确定后,第二行···也就随之确定了


代码:

#include <cstdio>
#include <cstring>
#define INF 0x7fffffff
#define MAXN 17
using namespace std;
const int dx[5]={-1,0,0,0,1};
const int dy[5]={0,-1,0,1,0};
int m,n,res,num;
int g[MAXN][MAXN];
int opt[MAXN][MAXN];///保存最优解
int flip[MAXN][MAXN];///保存中间结果
int get(int x,int y){
    int c=g[x][y];
    for(int d=0;d<5;++d) c+=flip[(x+dx[d])][(y+dy[d])];
    return c&1;
}
void calc(){
    for(int i=2;i<=m;++i) for(int j=1;j<=n;++j)
        if(get(i-1,j)){
            flip[i][j]=1;num++;
            if(num>=res) {num=INF;return;}
        }
    for(int j=1;j<=m;++j)if(get(m,j)){
        num=INF;return;
    }
}
bool solve(){
    res=INF;
    int sizet=1<<n;
    for(int i=0;i<sizet;++i){
        if(res<=1) return true;
        memset(flip,0,sizeof(flip));
        num=0;
        for(int j=1;j<=n;++j)
            if(i>>(n-j)&1){
                flip[1][j]=1;
                num++;
                if(num>=res) break;
            }
        if(num>=res) continue;
        calc();
        if(num<res){
            res=num;
            memcpy(opt,flip,sizeof(flip));
        }
    }
    if(res==INF) return false;
    else return true;
}
int main(){
    while(scanf("%d%d",&m,&n)!=EOF){
        for(int i=1;i<=m;++i) for(int j=1;j<=n;++j)
            scanf("%d",&g[i][j]);
        if(!solve()) {printf("IMPOSSIBLE\n");continue;}
        for(int i=1;i<=m;++i){
            for(int j=1;j<n;++j)
                printf("%d ",opt[i][j]);
            printf("%d\n",opt[i][n]);
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值