1. 程式人生 > >poj 3279 Fliptile (簡單搜索)

poj 3279 Fliptile (簡單搜索)

enter 分享 lse 所有 cstring ecif guess farm name

Fliptile
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 16558 Accepted: 6056

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

Sample Output

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

題目鏈接:

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

題目大意:

給你一個n*m的由0和1組成的矩陣A。一個對應的n*m的01矩陣B,若B的某元素為1,則矩陣A對應位置上下左右及自己五個位置發生反轉,即0變為1,1變為0。求字典序最小的矩陣B,使得A變為全0。(做完發現該字典序是反的即從右到左,算一個坑點吧)。由於重復反轉效果是一樣的,所以這題理解成這樣是沒有錯誤的。

簡單搜索題。

這題思路比較奇特。從i枚舉到1<<n,模擬第一行的反轉狀態。用位運算獲得每一位是1還是0。就是代碼中的 i&(i<<j)。然後根據第一行的反轉結果,就能完全確定接下來所有行的反轉狀態和反轉結果。這是因為若第一行某一位反轉後為1,只有通過下一行此處反轉才能變為0。如此,最後只要判斷最後一行是否為全0。若全為0,立即輸出便是字典序最小的結果。具體細節可以參考我的代碼體會一哈^_^。

技術分享圖片
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>

using namespace std;

int tile[20][20];
int ttile[20][20];
int oper[20][20];

int main()
{
    int m,n;
    scanf("%d%d",&m,&n);
    for(int i=0;i<m;i++)
        for(int j=0;j<n;j++)
            scanf("%d",tile[i]+j);

    int fflag=false;
    for(int i=0;i<(1<<n);i++)//枚舉第一行的翻轉
    {
        memcpy(ttile,tile,sizeof(tile));

        for(int j=0;j<n;j++)//處理第一行的翻轉
        {
            int op;
            if((i&(1<<j))>0)
                op=oper[0][j]=1;
            else
                op=oper[0][j]=0;
            ttile[0][j]^=op;
            if(j-1>=0)
                ttile[0][j-1]^=op;
            if(j+1<n)
                ttile[0][j+1]^=op;
            if(m>1)
                ttile[1][j]^=op;
        }

        for(int j=1;j<m;j++)//處理2..m行的翻轉
        {
            for(int k=0;k<n;k++)
            {
                int op;
                if(ttile[j-1][k]==1)
                    op=oper[j][k]=1;
                else
                    op=oper[j][k]=0;
                ttile[j][k]^=op;
                ttile[j-1][k]^=op;
                if(k-1>=0)
                    ttile[j][k-1]^=op;
                if(k+1<n)
                    ttile[j][k+1]^=op;
                if(j+1<m)
                    ttile[j+1][k]^=op;
            }
        }

        int flag=true;
        for(int i=0;i<n;i++)//判斷最後一行是否符合條件
        {
            if(ttile[m-1][i]==1)
            {
                flag=false;
                break;
            }
        }

        if(flag)
        {
            fflag=true;
            break;
        }
    }

    if(fflag)
    {
        for(int i=0;i<m;i++)
            for(int j=0;j<n;j++)
            {
                if(j==n-1)
                    printf("%d\n",oper[i][j]);
                else
                    printf("%d ",oper[i][j]);
            }
    }
    else
        printf("IMPOSSIBLE\n");
    return 0;
}
View Code

poj 3279 Fliptile (簡單搜索)