欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

POJ - 3279 Fliptile (反转,二维的)

程序员文章站 2022-05-18 16:01:20
...

题目链接

黑白格,最后是否能全部变成白色的。

每次翻转,会连同当前点的上下左右一起翻转。

 

这个题和一维的差不多。

先确定第一行的情况,每一行的情况根据上一行的的情况确定。

第一行的情况是有  1<<m  种,一行 m 个元素。

每种情况都用一次。

 

#include <cstring>
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#define mem(x,v) memset(x,v,sizeof(x))
const int N = 30;
int a[N][N],f[N][N],g[N][N],n,m;
int calc(){
    int ans = 0;
    for (int i = 2; i <= n; i++){
        for (int j = 1; j <= m; j++)
            if ((a[i-1][j]+f[i-1][j]+f[i-1][j+1]+f[i-1][j-1]+f[i-2][j]) % 2 == 1 ) //判断上一个节点是不是黑色的,
                f[i][j]= 1;
    }
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
            ans += f[i][j]; //之前忘记加上第一行了。一直 Wrong。
    for (int i = 1; i <= m; i++){
        if ((f[n][i] +a[n][i] + f[n][i-1] + f[n][i+1] + f[n-1][i]) % 2 == 1 ) return -1;
    }
    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 t,sum = -1;
    for (int i = 0; i < 1 << m; i++){
            mem(f,0);
        int x = m,y = i;
        while(y > 0){
            f[1][x--] = y & 1; y /= 2; //字典序输出,所以x要从大到小
        }
        t = calc();
            if (t >= 0 && (t < sum || sum < 0)){ //在这个地方错了半天,还有不需要动的数据。
                sum = t;
                for (int j = 1; j <= n; j++)
                    for (int k = 1; k <= m; k++)
                        g[j][k] = f[j][k];
            }

    }
    if (sum < 0) printf("IMPOSSIBLE\n"); else
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j < m; j++)
                printf("%d ",g[i][j]);
                printf("%d\n",g[i][m]);
        }
    return 0;
}

 

相关标签: 反转