POJ3279 Fliptile

题目大意

给定一个N*M的网格,每个网格里有一个数字,0或者1,要求你翻转尽量少的网格,使得所有网格的数字都变为0,对于某一个网格进行翻转操作时,与它有公共边的网格全部会被翻转。

题解

Uva11464的方法一样,都是枚举第一行的状态,只要第一行的状态确定了,那么每行的状态都确定了。

代码

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAXN 20
int a[MAXN][MAXN],b[MAXN][MAXN],ans[MAXN][MAXN];
int n,m;
int check(int s)
{
    int i,j;
    for(i=0; i<m; i++)
        if(s&(1<<i))
        {
            ans[0][i]=1;
            b[0][i]^=1;
            if(1<n) b[1][i]^=1;
            if(i-1>=0) b[0][i-1]^=1;
            if(i+1<m) b[0][i+1]^=1;
        }

    for(i=1; i<n; i++)
        for(j=0; j<m; j++)
            if(b[i-1][j])
            {
                ans[i][j]=1;
                b[i][j]^=1;
                b[i-1][j]^=1;
                if(i+1<n) b[i+1][j]^=1;
                if(j-1>=0)b[i][j-1]^=1;
                if(j+1<m) b[i][j+1]^=1;
            }
    for(i=0;i<m;i++)
    if(b[n-1][i]) return 0;
    return 1;
}
void print()
{
    int i,j;
    for(i=0; i<n; i++)
    {

        for(j=0; j<m-1; j++)
            printf("%d ",ans[i][j]);
        printf("%d\n",ans[i][j]);
    }
}
int main(void)
{
    int i,j,flag;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
    for(i=0; i<n; i++)
        for(j=0; j<m; j++)
            scanf("%d",&a[i][j]);
    flag=0;
    for(i=0; i<(1<<m); i++)
    {
        memcpy(b,a,sizeof(a));
         memset(ans,0,sizeof(ans));
        if(check(i))
        {
            flag=1;
            print();
            break;
        }
    }
    if(!flag)
        printf("IMPOSSIBLE\n");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/zjbztianya/p/2998470.html