zoukankan      html  css  js  c++  java
  • POJ 3279 Fliptile

    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 4
    1 0 0 1
    0 1 1 0
    1 0 0 1
    0 1 1 0

    Sample Output

    0 0 0 0
    1 0 0 1
    0 0 0 0
    1 0 0 1

    这个是一个反转的问题,参考上一次学习的反转问题http://blog.csdn.net/chilumanxi/article/details/46367927
    那个问题可以从左向右依次确定状态,最先确定的是第一个元素的状态。第一个元素的状态确定后,后面的元素状态随之确定。但是这个题面临的问题是即使是从上向下反转,那么每个点也会有多种反转方式,所以我们需要像那个题一样,确定第一排的状态,然后依次向后推,这样从第二排开始改状态,就可以有针对性了。
    用二进制枚举第一行的状态。然后搜索后面的情况。第一行共有2的N次幂个状态,对每个状态进行枚举
    创建三个数组,用来存储输入的数组,操作的数组和输出的数组,一些在处理的时候边界的细节问题见代码
    代码如下:
    /*************************************************************************
    	> File Name: Fliptile.cpp
    	> Author: Zhanghaoran0
    	> Mail: chiluamnxi@gmail.com
    	> Created Time: 2015年07月25日 星期六 15时10分09秒
     ************************************************************************/
    
    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #define maxn 20
    
    using namespace std;
    
    int N, M;
    int a[maxn][maxn], b[maxn][maxn];
    int output[maxn][maxn]; 
    bool flag = false;
    
    bool check(int x){
        for(int i = 0; i < N; i ++){
            if(x & (1 << i)){
                output[0][i] = 1;
                b[0][i] ^= 1;
                if(M > 1)
                    b[1][i] ^= 1;
                if(i - 1 >= 0)
                    b[0][i - 1] ^= 1;
                if(i + 1 < N)
                    b[0][i + 1] ^= 1;
            }
        }
    
        for(int i = 1; i < M; i ++){
            for(int j = 0; j < N; j ++){
                if(b[i - 1][j]){
                    output[i][j] = 1;
                    b[i][j] ^= 1;
                    b[i - 1][j] ^= 1;
                    if(i + 1 < M)
                        b[i + 1][j] ^= 1;
                   if(j - 1 >= 0)
                        b[i][j - 1] ^= 1;
                    if(j + 1 < N)
                       b[i][j + 1] ^= 1;
                    }
                }
            }
    
            for(int i = 0; i < N; i ++){
                if(b[M - 1][i])
                    return false;
            }
        return true;
    }
    
    
    int main(void){
        while(scanf("%d%d", &M, &N) != EOF){
            for(int i = 0; i < M; i ++){
                for(int j = 0; j < N; j ++){
                    cin >> a[i][j];
                }
            }
            flag = false;
            for(int i = 0; i < (1 << N); i ++){
                memcpy(b, a, sizeof(a));
                memset(output, 0, sizeof(output));
                if(check(i)){
                    flag = true;
                    for(int k = 0; k < M; k ++){
                        for(int j = 0; j < N; j ++){
                            cout << output[k][j] << " ";
                        }
                        cout << endl;
                    }
                    break;
                }
            }
            if(!flag)
                cout << "IMPOSSIBLE" << endl;
        }
        return 0;
    }


  • 相关阅读:
    ACM的探索之Keen On Evrything But Triangle(我觉得可以很接近啦!!)
    ACM的探索之Just Skip The Problem
    ACM的探索之Everything Is Generated In Equal Probability(这真的是很有趣的话语丫!)
    心情散记
    识别有效的IP地址和掩码并进行分类统计
    网络流复习计划
    CF1076D Edge Deletion
    bzoj4563 HAOI2016放旗子
    BZOJ2152聪聪可可
    BZOJ3224普通平衡树
  • 原文地址:https://www.cnblogs.com/chilumanxi/p/5136103.html
Copyright © 2011-2022 走看看