翻转问题开关问题 poj 3279 fliptile

题目:

https://vjudge.net/problem/POJ-3279

参考的题解:

POJ-3279 经典翻转问题_越努力越幸运—liupu-CSDN博客

翻转吧!POJ 3279! - 知乎 (zhihu.com)

思路:
把第一排的01串给枚举出来(直接按照字典序来)

 

从第二排开始把每种情况用b存下来

检查每种情况最后一排有没有黑色

如果全白从第一排开始把总的翻转次数算出来

#include<cstdio>
#include<string.h>
int a[20][20];
int b[20][20];
int c[20][20];
int n,m;
const int inf=0x3f3f3f3f;
int d[5][2]={{1,0},{0,1},{-1,0},{0,-1},{0,0}};
int get(int x,int y)
{
int res=a[x][y];
for(int i=0;i<5;i++)
{
    int fx=x+d[i][0];
    int fy=y+d[i][1];
    if(fx>=1&&fx<=n&&fy>=1&&fy<=m)
    {
        res+=b[fx][fy];
    }

}
   return res%2;
}
int slove()
{
    int ans=0;
    for(int i=2;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(get(i-1,j))
                b[i][j]=1;
        }
    }
    //检查最后一排
    for(int j=1;j<=m;j++)
    {
        if(get(n,j))
            return inf;
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
            ans+=b[i][j];
    }
    return ans;
}
int main()
{
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
            scanf("%d",&a[i][j]);
    }
    int fi=inf;
    for(int s=0;s<(1<<m);s++)
    { memset(b,0,sizeof(b));
        for(int j=1;j<=m;j++)
        {
            b[1][j]=(s>>(m-j))&1;
        }
       int te=slove();
       if(te<fi)
       {
           fi=te;
           memcpy(c,b,sizeof(b));
       }
    }
    if(fi==inf)
        printf("IMPOSSIBLE\n");
    else
    {
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                printf("%d ",c[i][j]);
            }
            printf("\n");
        }
    }
}

 

上一篇:P1144 最短路计数


下一篇:Nginx配置文件nginx.conf中文详解