POJ3279 Fliptile

来源:互联网 发布:开票软件v2.0 编辑:程序博客网 时间:2024/06/08 23:39

题意:

给一个由0,1组成的m*n的矩阵,要将所有的1转为0,求最小步数

每翻转一个,它的上下左右都会跟着翻转

思路:

二进制枚举第一行的所有情况,用一个二维数组记录翻转情况,翻转为1,不翻转为0

从第二行开始,判断(i - 1, j)是否为1,为1的话就要翻转(i, j),因为此时只有(i, j)可以影响到(i - 1, j)

最后判断一下最后一行是否全部为0

在所有符合的情况下选择最小的

代码如下:

#include <cstdio>#include <cstring>#include <iostream>using namespace std;const int INF = 1e7 + 10;int m, n;int a[20][20], mp[20][20], s[20][20];int f[5][2] = {0, 1, 1, 0, 0, 0, -1, 0, 0, -1};bool judge(int x, int y)//判断(i, j)的正反 {int cnt = a[x][y];for(int i = 0; i < 5; i++){int xx = x + f[i][0];int yy = y + f[i][1];if(xx >= 0 && xx < m && yy >= 0 && yy < n)            cnt += mp[xx][yy];}return cnt % 2;}int main(){while(~scanf("%d%d", &m, &n)){for(int i = 0; i < m; i++)    for(int j = 0; j < n; j++)        scanf("%d", &a[i][j]);        int ans = INF;        bool flag = false;        for(int i = 0; i < (1 << n); i++)        {        memset(mp, 0, sizeof(0));        int tmp = 0;        for(int j = 0; j < n; j++){mp[0][n - j - 1] = (i >> j) & 1;tmp += mp[0][n - j - 1];} for(int j = 1; j < m; j++){for(int k = 0; k < n; k++){if(judge(j - 1, k)){mp[j][k] = 1;tmp++;}}}flag = false;for(int j = 0; j < n; j++)//判断最后一行是否都为0{if(judge(m - 1, j)){flag = true;  break;} }if(!flag && tmp < ans){ans = tmp;memcpy(s, mp, sizeof(mp));}          }        if(ans == INF) puts("IMPOSSIBLE");        else{for(int i = 0; i < m; i++){for(int j = 0; j < n; j++){printf("%d%c", s[i][j], j == n - 1?'\n':' ');}}} }return 0;}


0 0
原创粉丝点击