poj-3279 Fliptile

Posted on 2017-02-06 15:03  Ramzey  阅读(132)  评论(0)    收藏  举报

题目传送门

题意:

  给一块n*m的地板,每块地板有黑白两种颜色,1是黑,0是白。如果翻动一块地板,那么包括它在内的上下左右五块地板都将翻转。问题是求最少翻转哪些地板能让所有地板都为白色。

  首先对于每个砖块来说,翻两次和不翻是没有区别的,所以每个砖块最多翻一次。那么我们从上面第一行开始看,因为每一次对板子操作都会影响其周围周围的板子。所以,每次想要改变黑色板子(1)的时候,都要翻其下面的板子,如果一个板子的上、左、右及其本身确定,那么下面的也就确定。

  如果第一行的板子确定了,那么以下的板子也就确定了,所以先枚举第一行的所有形式。如果所有板子都确定了,就应该开始判断最后一行是否还有黑色。

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAX = 20;
int num[MAX][MAX],t[MAX][MAX],ans[MAX][MAX];
int minn=0x3f3f3f3f;
bool judge(int n,int m)
{
    for(int i=1;i<=m;i++)
        if((num[n][i]+t[n][i]+t[n-1][i]+t[n][i-1]+t[n][i+1])&1)    
            return false;
    return true;
}
void dfs(int n,int m,int k,int step)
{
    if(step>minn)
        return;
    if(k>n)
    {
        if(judge(n,m)&&minn>step)
        {
            memcpy(ans,t,sizeof(t));
            minn=step;
        }
        return;
    }
    int cnt=0;
    for(int i=1;i<=m;i++)
    {
        if((num[k-1][i]+t[k-2][i]+t[k-1][i]+t[k-1][i-1]+t[k-1][i+1])&1)
        {
            t[k][i]=1;
            cnt++;
        }
        else
            t[k][i]=0;
    }
    dfs(n,m,k+1,step+cnt);
}
void direction(int n,int m,int k,int step)
{
    if(k>m)
    {
        dfs(n,m,2,step);
        return;
    }
    t[1][k]=0;
    direction(n,m,k+1,step);
    t[1][k]=1;
    direction(n,m,k+1,step+1);
}
int main(void)
{
    int n,m;
    while(cin>>n>>m)
    {
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                cin>>num[i][j];
        direction(n,m,1,0);
        if(minn==0x3f3f3f3f)
            cout<<"IMPOSSIBLE"<<endl;
        else
        {
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=m;j++)
                    cout<<ans[i][j]<<" ";
                cout<<endl;
            }
        }
    }
    return 0;
}

“(num[k-1][i]+t[k-2][i]+t[k-1][i]+t[k-1][i-1]+t[k-1][i+1])&1”

这句话是求 t[k][i]上面的板子是不是黑色  别忘了(* ̄∇ ̄*)

拿这组数据说

3 3

1 0 0    它第一行共有7种形式,就是二进制的0~7。      

1 1 0    

0 0 1

这组数据的解是

1 0 1

0 0 1

0 0 0

当第一行确定之后,地板就变成了这样

0 0 1

0 1 1

0 0 1

当n=2,m=3时,它上面是1所以它需要翻转

(num[k-1][i]+t[k-2][i]+t[k-1][i]+t[k-1][i-1]+t[k-1][i+1])&1

=(0+0+1+0+0)&1=1 所以它需要翻转

这个题还是挺好的所以写个随笔没事自己看看。