POJ 3279-Fliptile(母牛翻方格-開關問題)
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 6893 | Accepted: 2616 |
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
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
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
Source
題目意思:
農夫約翰知道聰明的牛產奶多。於是為了提高牛的智商他準備瞭如下游戲。有一個M×N 的格子,每個格子可以翻轉正反面,它們一面是黑色,另一面是白色。黑色的格子翻轉後就是白色,白色的格子翻轉過來則是黑色。遊戲要做的就是把所有的格子都翻轉成白色。不過因為牛蹄很大,所以每次翻轉一個格子時,與它上下左右相鄰接的格子也會被翻轉。因為翻格子太麻煩了,所以牛都想通過儘可能少的次數把所有格子都翻成白色。現在給定了每個格子的顏色,請求出用最小步數完成時每個格子翻轉的次數。最小步數的解有多個時,輸出字典序最小的一組。解不存在的話,則輸出IMPOSSIBLE。
解題思路:
首先,同一個格子翻轉兩次的話就會恢復原狀,所以多次翻轉是多餘的。此外,翻轉的格子的集合相同的話,其次序是無關緊要的。因此,總共有2NM種翻轉的方法。不過這個解空間太大了,我們需要想出更有效的辦法。讓我們再回顧一下前面的問題。在那道題中,讓最左端的牛反轉的方法只有1種,於是用直接判斷的方法確定就可以了。同樣的方法在這裡還行得通嗎?不妨先看看最左上角的格子。在這裡,除了翻轉(1,1)之外,翻轉(1,2)和(2,1)也可以把這個格子翻轉,所以像之前那樣直接確定的辦法行不通。於是不妨先指定好最上面一行的翻轉方法。此時能夠翻轉(1,1)的只剩下(2,1)了,所以可以直接判斷(2,1)是否需要翻轉。類似地(2,1)~(2,N)都能這樣判斷,如此反覆下去就可以確定所有格子的翻轉方法。最後(M,1)~(M,N)如果並非全為白色,就意味著不存在可行的操作方法。像這樣,先確定第一行的翻轉方式,然後可以很容易判斷這樣是否存在解以及解的最小步數是多
少,這樣將第一行的所有翻轉方式都嘗試一次就能求出整個問題的最小步數。這個演算法中最上面一行的翻轉方式共有2N種,複雜度為O(MN2N)。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<malloc.h>
using namespace std;
const int MAXN=16;
const int inf=0x3f3f3f3f;
const int dx[5]= {-1,0,0,0,1};//鄰接格子的方向
const int dy[5]= {0,-1,0,1,0};
int M,N;//長寬
int tile[MAXN][MAXN];//初始狀態
int flip[MAXN][MAXN];//中間結果翻轉次數
int opt[MAXN][MAXN];//最優解
int get(int x,int y)//查詢x,y的顏色
{
int c=tile[x][y];
for(int i=0; i<5; ++i)
{
int x2=x+dx[i];
int y2=y+dy[i];
if(x2>=0&&x2<M&&y2>=0&&y2<N)
c+=flip[x2][y2];
}
return c&1;//奇數為1,偶數為0
}
//求出第一行確定情況下的最小操作次數
//不存在解的話輸出-1
int calc()
{
//求出第2行開始的翻轉方法
for(int i=1; i<M; ++i)
for(int j=0; j<N; ++j)
if(get(i-1,j)!=0)//0白1黑,是黑色則翻轉
flip[i][j]=1;
//判斷最後一行是否全白
for(int j=0; j<N; ++j)
if(get(M-1,j)!=0)
return -1;
int res=0;//統計翻轉次數
for(int i=0; i<M; ++i)
for(int j=0; j<N; ++j)
res+=flip[i][j];
return res;
}
void solve()
{
int res=-1;
for(int i=0; i< (1<<N); ++i) //按字典序嘗試第一行的所有可能性
{
memset(flip,0,sizeof(flip));
for(int j=0; j<N; j++)
flip[0][N-j-1] = i>>j&1;
int num=calc();//計算反轉次數
if(num>=0&&(num<res||res<0))
{
res=num;
memcpy(opt,flip,sizeof(flip));//更新最優解
}
}
if(res<0) puts("IMPOSSIBLE");
else
for(int i=0; i<M; ++i)
for(int j=0; j<N; ++j)
printf("%d%c",opt[i][j],j+1==N?'\n':' ');
}
int main()
{
while(cin>>M>>N)
{
for(int i=0; i<M; ++i)
for(int j=0; j<N; ++j)
scanf("%d",&tile[i][j]);
solve();
}
return 0;
}
相關文章
- php演算法:母牛生小牛問題PHP演算法
- 網路流24題09方格取數問題
- POJ3984-迷宮問題
- 翻譯 | SpringBoot相關的面試問題Spring Boot面試
- poj 1321 棋盤問題 回溯 JavaJava
- 題解1236:母牛生小牛 (Java描述)Java
- 第七章 遞迴、DFS、剪枝、回溯等問題 ------------- 7.3 題解:機器人走方格問題遞迴機器人
- POJ 3264 Balanced Lineup【RMQ問題】MQ
- POJ1700 Crossing River 過河問題ROS
- poj 1182 並查集經典問題並查集
- 演算法系列-動態規劃(3):找零錢、走方格問題演算法動態規劃
- [翻譯]K-99問題解答
- 批次查詢的翻頁問題
- poj--2019Cornfields+二維RMQ問題MQ
- SAP Spartacus Translation(翻譯) 相關話題
- 關於struts開發時遇到的問題
- 丁奇:關於 AliSQL 開源大家關心的問題SQL
- 丁奇:關於AliSQL開源大家關心的問題SQL
- c++踩方格-動態規劃基礎題C++動態規劃
- [譯] 回答有關 Flutter App 開發的問題FlutterAPP
- 有關jboss開發EJB的JAR的問題?JAR
- 我們來看看翻譯中的問題
- 博弈論專題——推理與動態規劃相關博弈之POJ2484 POJ1740(模仿遊戲)動態規劃遊戲
- Docker 相關問題Docker
- 關於FastHashMap問題ASTHashMap
- django相關問題Django
- electron相關問題
- 【開發問題記錄①】關於滑動CollectionView時ContentSize變化的問題View
- POJ3468 A Simple Problem with Integers---樹狀陣列(區間問題)陣列
- 如何解決電腦桌面翻轉的問題?
- J2EE核心模式的翻譯問題模式
- 有關模型關聯的問題模型
- C語言遞迴之母牛的故事C語言遞迴
- 【轉載】POJ 圖論題目圖論
- 關於跨域問題跨域
- Java相關問題整理Java
- laravel orm 關聯問題LaravelORM
- PHP相關問題集合PHP