翻轉游戲題解

題目描述

翻轉游戲是這樣玩的:

有一張4*4的棋盤,在16個位置上每個位置放着一個棋子,棋子一面是黑色,另一面是白色,棋子或者白色面朝上,或者黑色面朝上。遊戲的走法如下:每一步先選擇一個位置,然後把該位置和上,下,左,右(不越界)相鄰位置上的棋子翻轉(白->黑,黑->白)。我們用w表示棋子白色面朝上,b表示黑色面朝上。

例如:考慮如下棋盤狀態:

bwbw

wwww

bbwb

bwwb

當我們選擇第三行,第一列的位置翻轉時,棋盤變化爲:

bwbw

bwww

wwwb

wwwb

遊戲的目的是用最少的步數把全部棋子變爲白色向上或黑色向上。

時限:1s

輸入格式

4行由b和w組成的字符串描述的一個棋盤的初始狀態。

輸出格式

一個測試數據輸出一行,爲所需要的最少的翻轉次數,如果無法翻轉成目標狀態,則輸出’impossible’(小寫,沒有引號)。

樣例輸入(1

bwbw

wwww

bbwb

bwwb

樣例輸出(1

Impossible

樣例輸入(2

bwwb

bbwb

bwwb

bwww

樣例輸出(2

4

 

解題思路:

BFS搜索加哈希判重。將w設置爲0,b設置爲1。把16個位置的數據當做二進制數,將二進制轉換爲十進制數。

2^16=65536,用於判重的哈希數組並不會很大,可以實現。

類似的題目還有八數碼問題,只不過八數碼的哈希表爲康託展開。八數碼:https://www.rqnoj.cn/problem/70

AC代碼:

#include<iostream>

#include<queue>

#include<cstring>

usingnamespace std;

 

typedefstruct table

{

   int pic[6][6];

}table;

 

tablestart;   //初始狀態

 

intP[16]={1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768};

boolvis[65536];  //狀態數組

intdist[65536];

queue<table>Q;

 

//黑0 白1

charNegate(int ch)

{

   if(ch)

      return 0;

   return 1;

}

 

voidturn(int x,int y,table &T)

{

   T.pic[x][y]=Negate(T.pic[x][y]); //自身

   T.pic[x][y-1]=Negate(T.pic[x][y-1]);   //左側

   T.pic[x][y+1]=Negate(T.pic[x][y+1]);   //右側

   T.pic[x-1][y]=Negate(T.pic[x-1][y]);   //上側

   T.pic[x+1][y]=Negate(T.pic[x+1][y]);   //下側

}

 

intget_dec(table T)    //位壓縮 

{

   int dec=0;

   int s=0;

   for(int i=4;i>0;--i)

   for(int j=4;j>0;--j)

   {

      dec+=T.pic[i][j]*P[s];

      s++;

   } 

   return dec;

}

 

intBFS()

{

   Q.push(start); //初始狀態入隊

   int st=get_dec(start);    //獲取索引

   vis[st]=true;

   int front=1,rear=2;

   table Now;

   while(front<rear)

   {

      Now=Q.front();   //頭結點出隊

      Q.pop();

      int index=get_dec(Now);   //獲取索引

      if(index==0||index==65535)   //找到終點

        return front;

      for(int i=0;i<16;++i)

      {

        int x=i/4+1;   //橫座標 

        int y=i%4+1;   //縱座標

        table Next=Now;

        turn(x,y,Next);   //變換求下一步

        int ni=get_dec(Next);

        if(!vis[ni])

        {

           vis[ni]=true;

           Q.push(Next);

           dist[rear]=dist[front]+1;

           rear++;

        }

      }

      front++;

   }

   return -1;

}

intmain()

{

   for(int i=0;i<6;++i)

   for(int j=0;j<6;++j)

      start.pic[i][j]=0;

   memset(vis,0,sizeof(vis));

   for(int i=1;i<=4;++i)

   for(int j=1;j<=4;++j)

   {

      char ch;

      cin>>ch;

      if(ch=='w')

        start.pic[i][j]=0;

      else

        start.pic[i][j]=1;    

   }

   int s=BFS();

   if(s!=-1)

      cout<<dist[s]<<endl;

   else

      cout<<"impossible"<<endl;

   return 0;

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章