Fliptile POJ -状压枚举第一层

  • Fliptile

  •  POJ - 3279 
  • 题意:
  • 牛可以踩格子保证求一个最少踩的次数,最小状态下输出每个位置踩的次数
  • 思路:
  • 枚举第一层的状态依次就可以确定下面的状态。
  • 注意递归回溯图修改恢复的处理。
  • #include <iostream>
    #include<cstring>
    #include<stdio.h>
    #include<algorithm>
    using namespace std;
    #define maxn 22
    #define inf 0x3f3f3f3f
    #define ll long long
    ll t,n,m,ans,sum=inf;
    char gra[maxn][maxn],mmp[maxn][maxn],out[maxn][maxn],in[maxn][maxn],pr[maxn][maxn];
    void check(int s)
    {
        memcpy(pr,out,sizeof(out));
        for(int i=1; i<n; i++)
            for(int j=0; j<m; j++)
            {
                if(mmp[i-1][j]=='1')
                {
                    out[i][j]='1';
                    mmp[i][j]=='1'?mmp[i][j]='0':mmp[i][j]='1';
                    mmp[i-1][j]='0';
                    if(j>0)
                        mmp[i][j-1]=='1'?mmp[i][j-1]='0':mmp[i][j-1]='1';
                    if(j<m-1)
                        mmp[i][j+1]=='1'?mmp[i][j+1]='0':mmp[i][j+1]='1';
                    if(i<n-1)
                        mmp[i+1][j]=='1'?mmp[i+1][j]='0':mmp[i+1][j]='1';
                    s++;
                }
            }
        for(int i=0; i<m; i++)
            if(mmp[n-1][i]=='1')
            {
                memcpy(out,pr,sizeof(out));
                return ;
            }
        if(s<sum)
        {
            sum=s;
            memcpy(in,out,sizeof(out));
        }
        memcpy(out,pr,sizeof(out));
        return ;
    }
    void dfs(int cnt,int s)
    {
        if(cnt>m)
            return;
        if(cnt==m)
        {
            memcpy(gra,mmp,sizeof(mmp));
            check(s);
            memcpy(mmp,gra,sizeof(mmp));
            return ;
        }
        out[0][cnt]='0';
        dfs(cnt+1,s);
        out[0][cnt]='1';
        if(mmp[0][cnt]=='1')
        {
            mmp[0][cnt]='0';
            if(cnt>0)
                mmp[0][cnt-1]=='1'?mmp[0][cnt-1]='0':mmp[0][cnt-1]='1';
            if(cnt<m-1)
                mmp[0][cnt+1]=='1'?mmp[0][cnt+1]='0':mmp[0][cnt+1]='1';
            if(0<n-1)
                mmp[0+1][cnt]=='1'?mmp[0+1][cnt]='0':mmp[0+1][cnt]='1';
            dfs(cnt+1,s+1);
            out[0][cnt]='0';
            mmp[0][cnt]='1';
            if(cnt>0)
                mmp[0][cnt-1]=='1'?mmp[0][cnt-1]='0':mmp[0][cnt-1]='1';
            if(cnt<m-1)
                mmp[0][cnt+1]=='1'?mmp[0][cnt+1]='0':mmp[0][cnt+1]='1';
            if(0<n-1)
                mmp[0+1][cnt]=='1'?mmp[0+1][cnt]='0':mmp[0+1][cnt]='1';
        }
        else
        {
            if(cnt>0)
                mmp[0][cnt-1]=='1'?mmp[0][cnt-1]='0':mmp[0][cnt-1]='1';
            if(cnt<m-1)
                mmp[0][cnt+1]=='1'?mmp[0][cnt+1]='0':mmp[0][cnt+1]='1';
            if(0<n-1)
                mmp[0+1][cnt]=='1'?mmp[0+1][cnt]='0':mmp[0+1][cnt]='1';
            mmp[0][cnt]='1';
            dfs(cnt+1,s+1);
            out[0][cnt]='0';
            mmp[0][cnt]='0';
            if(cnt>0)
                mmp[0][cnt-1]=='1'?mmp[0][cnt-1]='0':mmp[0][cnt-1]='1';
            if(cnt<m-1)
                mmp[0][cnt+1]=='1'?mmp[0][cnt+1]='0':mmp[0][cnt+1]='1';
            if(0<n-1)
                mmp[0+1][cnt]=='1'?mmp[0+1][cnt]='0':mmp[0+1][cnt]='1';
        }
    }
    int main()
    {
        memset(out,'0',sizeof(out));
        scanf("%lld%lld",&n,&m);
        for(int i=0; i<n; i++)
        {
            for(int j=0; j<m; j++)
            {
                getchar();
                scanf("%c",&mmp[i][j]);
            }
        }
        dfs(0,0);
        if(sum==inf)
        {
            printf("IMPOSSIBLE\n");
            return 0;
        }
        for(int i=0; i<n; i++)
            for(int j=0; j<m; j++)
            {
                if(j!=m-1)
                {
                    printf("%c ",in[i][j]);
                }
                else
                {
                    printf("%c\n",in[i][j]);
                }
            }
        return 0;
    }
    

     

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值