POJ - 3279 Fliptile 【枚举+模拟】

版权声明:如需转载,记得标识出处 https://blog.csdn.net/godleaf/article/details/86702244

题目链接:http://poj.org/problem?id=3279

题意:0代表白色,1代表黑色,每翻一个瓷片,上下左右的瓷片会跟着一起翻,要求翻动次数最小并且答案的字典排序最小。答案是一个矩形,代表的意思是对应位置的瓷片翻动几次,如果不存在就输出IMPOSSIBLE。

思路:

因为翻动一个瓷片会影响四周的瓷片,所以要一层一层的完成翻动,比如说我要把第一层的全部翻成白色,最好的办法是翻动第二层的瓷片,间接的翻动第一层的瓷片,而且还不会影响第一层的其他瓷片,如果倒数第二层的瓷片都翻完,最后一层还有黑色的瓷片,那么这种方案就是不可行的。

原本以为第一层的不动,从第二层开始翻就能得出答案,但事实上,第一层不动,如果方案不可行,未必就没有其他方法。所以我们要枚举第一层的所有情况,因为 M <= 15,所以第一层有 2^15种情况,只需要枚举第一层的情况,然后再做上面的操作求出答案就行了。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <set>
#include <queue>

using namespace std;

typedef long long ll;

const int INF = 0x3f3f3f3f;
const int Maxn = 1e5+10;

char G[20][20], ans[20][20], tmp[20][20], g[20][20];
int N, M, cnt;

void filp(int i, int j) {
    if(i > 0) g[i-1][j] = g[i-1][j] == '1' ? '0' : '1';
    if(j > 0) g[i][j-1] = g[i][j-1] == '1' ? '0' : '1';
    if(j+1 < M) g[i][j+1] = g[i][j+1] == '1' ? '0' : '1';
    if(i+1 < N) g[i+1][j] = g[i+1][j] == '1' ? '0' : '1';
    g[i][j] = g[i][j] == '1' ? '0' : '1';
}

int main(void)
{
    cin >> N >> M;
    for(int i = 0; i < N; ++i)
        for(int j = 0; j < M; ++j)
            cin >> G[i][j];

    int cnt = INF;
    for(int i = 0; i < (1<<M); ++i) {
        memset(tmp, 0, sizeof(tmp));
        memcpy(g, G, sizeof(g));
        int ct = 0;
        for(int j = M-1; j >= 0; --j) {
            if((i>>(M-1-j)&1) == 1) {
                tmp[0][j] = '1';
                filp(0, j); ct++;
            } else tmp[0][j] = '0';
        }

        for(int ii = 1; ii < N; ++ii) {
            for(int jj = 0; jj < M; ++jj) {
                if(g[ii-1][jj] == '1') {
                    filp(ii, jj);
                    tmp[ii][jj] = '1';
                    ct++;
                } else tmp[ii][jj] = '0';
            }
        }
        bool ok = true;
        for(int ii = 0; ii < M; ++ii) if(g[N-1][ii] == '1') ok = false;
        if(ok && ct < cnt) {
            cnt = ct; memcpy(ans, tmp, sizeof(ans));
        }
    }
    if(cnt == INF) cout << "IMPOSSIBLE" << endl;
    else {
        for(int i = 0; i < N; ++i) {
            for(int j = 0; j < M; ++j) {
                cout << ans[i][j];
                if(j < M-1) cout << " ";
            }
            cout << endl;
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/godleaf/article/details/86702244