1. 程式人生 > 其它 >學習隨筆——POJ題目1753:Flip Game解答

學習隨筆——POJ題目1753:Flip Game解答

相關題目連結:http://poj.org/problem?id=1753

題目截圖如下:

 

 題目大意:在4*4棋盤上有黑白子若干,現需要翻動若干次棋盤上的棋子實現棋盤上的棋子全白或全黑。翻動的規則是:當翻動某一棋子時,其上下左右棋子也需被翻動。求翻動的最小次數,如果無法實現,則需要輸出提示資訊“Impossible”。

一道列舉的題目,根據分析,我們很容易知道同一個位置的棋子翻動兩次與未翻動的狀態相同,所以每個位置的棋子我們就可簡化為翻動與不翻動兩種狀態。這樣只需確定16個位置的翻動狀況即可。同樣的,如果最後翻動次數大於16我們可以判定為不存在一種翻動的可行方案。

先放上程式碼,之後會對遞迴過程進行詳細講解:

 1 #include <stdio.h>
 2 #include <iostream>
 3 using namespace std;
 4 int mem[16] = {0};//化二維為一維的陣列 
 5 int ans = 100;//最後返回的回答
 6 void change (int pos){
 7     int x = pos/4;//判斷邊界條件 
 8     int y = pos%4;//判斷邊界條件 
 9     mem[pos] = !mem[pos];//先改變目標點 
10     if (x>0)
11         mem[pos-4] = !mem[pos-4
]; 12 if (x<3) 13 mem[pos+4] = !mem[pos+4]; 14 if (y>0) 15 mem[pos-1] = !mem[pos-1]; 16 if (y<3) 17 mem[pos+1] = !mem[pos+1]; 18 }//pos為要改變的點的座標 19 bool Judge (){ 20 for (int i = 0;i<15;i++){ 21 if (mem[i] != mem[i+1]) 22 return false
; 23 } 24 return true; 25 }//判斷是否實現預定目標 26 void Enum (int pos,int count){ 27 if (Judge()) 28 if (count < ans){ 29 ans = count; 30 return ; 31 } 32 if (pos >= 16) 33 return ; 34 change (pos); 35 Enum (pos+1,count+1); 36 change (pos); 37 Enum (pos+1,count); 38 return ; 39 } 40 int main (int argc,char *argv[]){ 41 char start; 42 for (int i=0;i<16;i++){ 43 cin>>start; 44 if (start=='b'){ 45 mem[i]=1; 46 } 47 } 48 Enum (0,0); 49 if (ans==100) 50 printf("Impossible"); 51 else 52 printf("%d",ans); 53 return 0; 54 }

對遞迴部分的講解:

1 change (pos);
2 Enum (pos+1,count+1);
3 change (pos);//復位操作
4 Enum (pos+1,count);

      我對於這四條語句的理解是,我們把它理解為一種狀態的轉換:每一個位置有翻與不翻兩種狀態,其中1、2兩句即表示該位置棋子翻轉,並將該狀態輸入函式的過程。第三句實際上實現了一種“復位”操作,將原來翻轉的棋子再翻轉回來,再將該位置棋子未翻轉的狀態輸入函式。事實上,上述語句改編為以下形式亦可。

1 Enum (pos+1,count);
2 change (pos);
3 Enum (pos+1,count+1);
4 change (pos);//復位操作