【POJ - 3279】Fliptile(經典翻轉問題)


-->Fliptile

直接中文翻譯:
Descriptions:

給你一個01矩陣,矩陣大小為M x N。(1 <= M , N <= 15)
每次操作選擇一個格子,使得該格子與上下左右四個格子的值翻轉。
至少多少次操作可以使得矩陣中所有的值變為0?
請輸出翻轉方案,若沒有方案,輸出"IMPOSSIBLE” 。
若有多種方案符合題意,請首先輸出翻轉次數最少的方案;若方案個數仍不唯一,則輸出字典序最小的方案。

Input

第一行輸入兩個數:M和N。(1 <= M , N <= 15)
接下來M行,每行N個數,其值只為0或1。

Output

輸出M行,每行N個數。
每個數代表該位置翻轉次數

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

題目鏈接:

https://vjudge.net/problem/POJ-3279

 

先按字典順序枚舉第一行的全部可能,再去推第2行,第3行......把這些行全部推成0,最后看最后一行,如果最后一行都是0,則成功,記錄翻轉次數。否則失敗

 

AC代碼:

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#define mod 1000000007
#define eps 1e-6
#define ll long long
#define INF 0x3f3f3f3f
#define MEM(x,y) memset(x,y,sizeof(x))
#define Maxn 20
using namespace std;
int result;
int n,m;
int mp[Maxn][Maxn];//原始地圖
int tmp[Maxn][Maxn];//當前操作的地圖
int ans[Maxn][Maxn];//最優解地圖
int dt[][2] = { { -1, 0 }, { 1, 0 }, { 0, 0 }, { 0, -1 }, { 0, 1 } };//5個方向
int getcolor(int x,int y)//得到(x,y)的顏色
{
    int cnt=mp[x][y];
    for(int i=0; i<5; i++)
    {
        int tx=dt[i][0]+x;
        int ty=dt[i][1]+y;
        if(tx>=0&&tx<n&&ty>=0&&ty<m)
            cnt+=tmp[tx][ty];
    }
    return cnt%2;
}
int solve()
{
    int cnt=0;
    for(int i=1; i<n; i++)//從第二行開始檢查是否需要翻轉
        for(int j=0; j<m; j++)
            if(getcolor(i-1,j))
                tmp[i][j]=1;
    for(int i=0; i<m; i++)//檢查最后一行是否全為0
        if(getcolor(n-1,i))
            return INF;
    for(int i=0; i<n; i++)//統計翻轉次數
        for(int j=0; j<m; j++)
            cnt+=tmp[i][j];
    return cnt;
}
int main()
{
    result=INF;
    cin>>n>>m;
    for(int i=0; i<n; i++)
        for(int j=0; j<m; j++)
            cin>>mp[i][j];
    for(int i=0; i<1<<m; i++)//按照字典序枚舉第一行所以翻轉可能
    {
        MEM(tmp,0);//初始化地圖
        for(int j=0; j<m; j++)
            tmp[0][j]= i>>(m-(j+1)) & 1;//第一行的狀態
        int sum=solve();//翻轉的次數
        if(sum<result)//更新地圖
        {
            result=sum;
            memcpy(ans,tmp,sizeof tmp);//tmp數組復制到ans
        }
    }
    if(result==INF)
        cout<<"IMPOSSIBLE"<<endl;
    else//輸出
    {
        for(int i=0; i<n; i++)
        {
            for(int j=0; j<m; j++)
                cout<<ans[i][j]<<" ";
            cout<<endl;
        }
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM