poj 3279--Fliptile(二维反转)

来源:互联网 发布:最优化pdf百度云 编辑:程序博客网 时间:2024/05/18 07:07

给一个0,1组成的矩阵,要将所有的1都反转成0,反转某一个的时候,起上下左右也一起反转。求翻动次数最小。

http://poj.org/problem?id=3279

二维反转。和一维反转相类似。我们从第一行开始考虑。

先二进制枚举出第一行的反转情况。

然后从第二行开始,如果(i - 1, j)为1,则反转(i, j)。因为此时只有(i, j)可以影响(i - 1, j)的正反。

最后检查一下最后一行是否都为0.

(在计算反转次数时,别忘了加上第一行的反转。。。(⊙_⊙))

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int inf = 0x3f3f3f3f;int dxy[5][2] = { {0, 1}, {1, 0}, {0, 0}, {-1, 0}, {0, -1} };int m, n, a[20][20], ans[20][20], opt[20][20];int judge(int x, int y){    //返回(i, j)的正反情况    int ret = a[x][y];    for(int i=0; i<5; i++){        int xx = dxy[i][0] + x;        int yy = dxy[i][1] + y;        if(xx >= 0 && xx < m && yy >= 0 && yy < n)            ret += opt[xx][yy];    }    return ret % 2;}int main(){    scanf("%d%d", &m, &n);    int ret = inf;    for(int i=0; i<m; i++)        for(int j=0; j<n; j++)            scanf("%d", &a[i][j]);    for(int i=0; i<(1 << n); i++){   //二进制枚举第一行        memset(opt, 0, sizeof(opt));        int res = 0;        for(int j=0; j<n; j++){            opt[0][n - j - 1] = (i >> j) & 1;            res += opt[0][n - j - 1];        }        for(int j=1; j<m; j++)            for(int k=0; k<n; k++)                if(judge(j - 1, k)) {                    opt[j][k] = 1;                    res++;                }        bool flag = true;        for(int j=0; j<n; j++) if(judge(m - 1, j)) {            flag = false;            break;        }        if(flag && res < ret){            ret = res;            memcpy(ans, opt, sizeof(opt));        }    }    if(ret == inf) puts("IMPOSSIBLE");    else {        for(int i=0; i<m; i++)            for(int j=0; j<n; j++) printf("%d%c", ans[i][j], j == n - 1 ? '\n' : ' ');    }    return 0;}



0 0