POJ 3279Fliptile

来源:互联网 发布:书店软件 编辑:程序博客网 时间:2024/06/14 17:51
Fliptile
Time Limit: 2000MS Memory Limit: 65536KTotal Submissions: 11299 Accepted: 4176

Description

Farmer John knows that an intellectually satisfied cow is a happy cow who will give more milk. He has arranged a brainy activity for cows in which they manipulate an M × N grid (1 ≤ M ≤ 15; 1 ≤ N ≤ 15) of square tiles, each of which is colored black on one side and white on the other side.

As one would guess, when a single white tile is flipped, it changes to black; when a single black tile is flipped, it changes to white. The cows are rewarded when they flip the tiles so that each tile has the white side face up. However, the cows have rather large hooves and when they try to flip a certain tile, they also flip all the adjacent tiles (tiles that share a full edge with the flipped tile). Since the flips are tiring, the cows want to minimize the number of flips they have to make.

Help the cows determine the minimum number of flips required, and the locations to flip to achieve that minimum. If there are multiple ways to achieve the task with the minimum amount of flips, return the one with the least lexicographical ordering in the output when considered as a string. If the task is impossible, print one line with the word "IMPOSSIBLE".

Input

Line 1: Two space-separated integers: M and N 
Lines 2..M+1: Line i+1 describes the colors (left to right) of row i of the grid with N space-separated integers which are 1 for black and 0 for white

Output

Lines 1..M: Each line contains N space-separated integers, each specifying how many times to flip that particular location.

Sample Input

4 41 0 0 10 1 1 00 1 1 01 0 0 1

Sample Output

0 0 0 01 0 0 11 0 0 10 0 0 0

题意:

一个M*N的方格(M、N均不超过15),每个格初始化为0或1,每翻动一个格子改变其数字也会改变其上下左右共计5个格子的数据,问将所有格子变为1的最小翻动次数下各个格子的翻动次数。

解题方法:

按照从上往下翻动改变的顺序(当然也可以选择其他三个方向),某一行必须由它下一行翻动改变为0,那么由上到下翻动时,只需确定第一行,则可确定余下所有行的翻动次数。假如每行有N个数,则共有2^m种不同翻动形式,因为每个格子可选择翻或者不翻。枚举所有翻动形式,维护翻动次数最小值,记录各个格子的翻动次数(最大为1)。

AC代码:

/*每个瓦片最多翻转一次*/
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int N = 17;
const int dx[] = {-1, 0, 1, 0, 0};
const int dy[] = { 0,-1, 0, 1, 0};
int grid[N][N]/*初始存储数组*/, state[N][N]/*变换数组*/, tmp[N][N]/*翻转次数中间储存函数*/, rec[N][N]/*翻转次数最终存储数组*/;
int n, m, ans;
void flip(int x, int y)///翻转处理函数
{
    tmp[x][y] = 1;
    int nx, ny;
    for(int i = 0; i < 5; i++)
    {
        nx = x+dx[i];
        ny = y+dy[i];
        state[nx][ny] = !state[nx][ny];
    }
}
bool isEmpty(int n)///判断是否翻转成功函数
{
    for(int j = 1; j <= m; j++)
    {
        if(state[n][j])
            return false;
    }
    return true;
}
void solve(int st)
{
    memcpy(state, grid, sizeof(grid));///复制grid初始存储数组,初始化
    memset(tmp, 0, sizeof(tmp));///tmp中间储存翻转数组
    int cnt = 0;
    for(int j = 0; j < m; j++)
    {
        if((st>>j) & 1)///判断st/(2^j)的奇偶性,奇数返回为yes
        {
            flip(1, j+1);
            cnt++;
        }
    }
    for(int i = 2; i <= n; i++)
    {
        for(int j = 1; j <= m; j++)
        {
            if(state[i-1][j] == 1)///只有下(上、左、右)面一行能影响上面一行,取决于遍历方向
            {
                flip(i, j);
                cnt++;
            }
        }
    }
    if(isEmpty(n) && cnt < ans)///翻转成功并且小于ans
    {
        ans = cnt;
        memcpy(rec, tmp, sizeof(tmp));
    }
}
int main()
{
    while(scanf("%d%d", &n, &m) != EOF)
    {
        for(int i = 1; i <= n; i++)///起始坐标为(1,1)
        {
            for(int j = 1; j <= m; j++)
            {
                scanf("%d", &grid[i][j]);
            }
        }
        ans = INF;///标记翻转次数变量
        int end = 1 << m;///end=2^m;
        for(int st = 0; st < end; st++)///每行有m个瓦片,每个瓦片可选择翻或者不翻,故有2^m种情况
            solve(st);
        if(ans == INF)///输出
            puts("IMPOSSIBLE");
        else
        {
            for(int i = 1; i <= n; i++)
            {
                printf("%d", rec[i][1]);
                for(int j = 2; j <= m; j++)
                    printf(" %d", rec[i][j]);
                puts("");
            }
        }
    }
    return 0;
}