1. 程式人生 > 實用技巧 >翻轉游戲

翻轉游戲

翻轉游戲

Descrption

  • 翻轉游戲是在一個 4×4

的正方形上進行的,在正方形的 16 個格上每個格子都放著一個雙面的物件。每個物件的兩個面,一面是白色,另一面是黑色,每個物件要麼白色朝上,要麼黑色朝上,每一輪你只能翻 35

個物件,從而由黑到白的改變這些物件上面的顏色,反之亦然。每一輪被選擇翻轉的物件遵循以下規則:

  1. 16
  1. 個物件中任選一個。
  2. 翻轉所選擇的物件的同時,所有與它相鄰的左方物件、右方物件、上方物件和下方物件(如果有的話),都要跟著翻轉。
  • 以下為例:

    bwbw
    wwww
    bbwb
    bwwb
    
    • 這裡 b

表示該格子放的物件黑色面朝上、

w

      • 表示該格子放的物件白色朝上。如果我們選擇翻轉第三行的第一個物件,那麼格子狀態將變為:
      bwbw
      bwww
      wwwb
      wwwb
      
  • 遊戲的目標是翻轉到所有的物件白色朝上或黑色朝上。你的任務就是寫一個程式來求最少的翻轉次數來實現這一目標。

Input

  • 輸入檔案包含 4

行,每行 4 個字元,每個字元 wb

  • 表示遊戲開始時格子上物件的狀態。

Output

  • 輸出檔案僅一個整數,即從給定狀態到實現這一任務的最少翻轉次數。如果給定的狀態就已經實現了目標就輸出 0,如果不可能實現目標就輸出: Impossible

Sample Input

bwwb
bbwb
bwwb
bwww

Sample Output

4

Hint

  • 根據資料範圍可知,本題可以暴力列舉。

  • 我們列舉第一行轉後的狀態,通過最終目標進而列舉第2行,從而使第一行合法,因為以後不會影響到第一行。最後判斷第4行
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
const int Inf=1<<16;
int cnt,ans=Inf;
char s[5][5],ss[5][5];
void C(char &a){
    if(a=='
w')a='b'; else if(a=='b')a='w'; } void F(int x,int y){ cnt++;//翻轉一次次數加1 C(ss[x][y]); C(ss[x-1][y]); C(ss[x][y-1]); C(ss[x+1][y]); C(ss[x][y+1]); } void W(int x,char y){//目標是全翻為y memcpy(ss,s,sizeof s);//拷貝原陣列 cnt=0; for(int i=1;i<=4;++i){//按照形參中規定的第一行翻轉後的狀態來翻轉,列舉第一行每一列 if(x&(1<<(i-1))){//若該點需翻轉(與形參中y不同) F(1,i);//就主動翻轉 } } for(int i=2;i<=4;++i){//列舉2~4行 for(int j=1;j<=4;++j){//列舉每一列 if(ss[i-1][j]!=y){//若上一行不是y的話 F(i,j);//就需要本行這一列來翻轉從而是上面的那個字元被動變為y } } }//迴圈結束後前3行全已經變為y了 for(int i=1;i<=4;++i){ if(ss[4][i]!=y)return; } ans=ans>cnt?cnt:ans;//若都能變為y,則第一行按x狀態翻轉所需要的步數對最終結果有貢獻 } int main(){ for(int i=1;i<=4;++i){ scanf("%s",s[i]+1); } for(int S=0;S<=15;++S){//因為還要翻轉第二行,所以第一行翻轉後可能是任意狀態,在此列舉 W(S,'w');W(S,'b'); } if(ans==Inf){ printf("Impossible\n"); }else printf("%d\n",ans); return 0; }