問題描述
如下面第乙個圖的九宮格中,放著 1~8 的數字卡片,還有乙個格仔空著。與空格子相鄰的格仔中的卡片可以移動到空格中。經過若干次移動,可以形成第二個圖所示的局面。
我們把第乙個圖的局面記為:12345678.
把第二個圖的局面記為:123.46758
顯然是按從上到下,從左到右的順序記錄數字,空格記為句點。
本題目的任務是已知九宮的初態和終態,求最少經過多少步的移動可以到達。
如果無論多少步都無法到達,則輸出-1。
輸入格式
輸入第一行包含九宮的初態,第二行包含九宮的終態。
輸出格式
輸出最少的步數,如果不存在方案,則輸出-1。
樣例輸入
12345678.
123.46758
樣例輸出
3樣例輸入
13524678.
46758123.
樣例輸出
22——分割線——
分析:本題和「歷屆試題 青蛙跳杯子」同屬一種型別
都是給出乙個初態和乙個目標態,讓我們輸出從初態轉變為目標態所需的最小步數
不同的是,在「歷屆試題 青蛙跳杯子」這道題中,我們處理的字串在發生位置交換時是乙個一維的變換(只有向左或向右,則對應用加或減來刻畫即可),並且對於所有位置上都通用,於是可以設定乙個dir陣列,在裡面存放所有的位置變換操作即可;而在本題中,由於給出的是乙個九宮格,因此在處理字串發生位置交換時是乙個二維的變換(此時有上、下、左、右四個方向的變換)。於是在這裡就引出了乙個新問題:每個點位置變換時並不一致,我們如何處理。如下所示:
我們可以發現:
與格點0直接相鄰的點有格點1和格點3(與之類似的還有格點2、格點6、格點8)
與格點1直接相鄰的點有格點0、格點2和格點4(與之類似的還有格點3、格點5、格點7)
與格點4直接相鄰的點有格點1、格點3、格點5和格點7
這時我們換一種思路,把這個九宮格視為乙個長度為9的字串(降維至一維):012345678
此時再把這字串上每個位置能直接移動過去的點都放進乙個陣列dir[ ][ ]中,如:
在點0處能移動至點1和點3,則dir[0][0]=1,dir[0][1]=3
在點1處能移動至點0、點2和點4,則dir[1][0]=0,dir[1][1]=2,dir[1][2]=4
在點4處能移動至點1、點3、點5和點7,則dir[4][0]=1,dir[4][1]=3,dir[4][2]=5,dir[4][3]=7
……由於從上圖的結論中我們知道,在九宮格中主要有三類點,一類的直接相鄰點為2,一類為3,還有乙個為4。因此為了在程式中能更方便使用dir[ ][ ],我們還需要為每個出發點設定好其可移動方案的數量,這裡可以再次定義乙個dircount[ ]陣列來存放,如:
在點0處能移動至其他兩個點,則dircount[0]=2
在點1處能移動至其他三個點,則dircount[1]=3
在點4處能移動至其他四個點,則dircount[4]=4
……當解決了上述問題後,這道題就和歷屆試題 青蛙跳杯子一樣了
接下來只需要利用bfs來對整個初始字串進行搜尋即可
——分割線——
下面直接給出本題的完整**:
#include
#include
#include
#include
using
namespace std;
//初始化每個點能直接移動過去的點
int dir[9]
[4]=
,,,,
,,,,
};int dircount=
;//每個點可移動方案的數量
struct situation
intgetpos()
//返回當前字串中 空格的位置 };
queue q;
set s;
void
bfs(string start,string target)
q.push
(situation
(start,0)
);s.insert
(start)
;while
(!q.
empty()
)if(!s.
count
(str)
)swap
(str[pos]
,str[dir[pos]
[i]]);
//恢復現場 }}
cout<
<
}int
main()
藍橋杯 歷屆試題 九宮重排
問題描述 如下面第乙個圖的九宮格中,放著 1 8 的數字卡片,還有乙個格仔空著。與空格子相鄰的格仔中的卡片可以移動到空格中。經過若干次移動,可以形成第二個圖所示的局面。我們把第乙個圖的局面記為 12345678.把第二個圖的局面記為 123.46758 顯然是按從上到下,從左到右的順序記錄數字,空格...
藍橋杯 歷屆試題 九宮重排
問題描述 如下面第乙個圖的九宮格中,放著 1 8 的數字卡片,還有乙個格仔空著。與空格子相鄰的格仔中的卡片可以移動到空格中。經過若干次移動,可以形成第二個圖所示的局面。我們把第乙個圖的局面記為 12345678.把第二個圖的局面記為 123.46758 顯然是按從上到下,從左到右的順序記錄數字,空格...
藍橋杯 歷屆試題 九宮重排
bfs 查重 因為通過不同的路徑到達同乙個點會產生不同的串,不具有唯一性,所以查重不再是查詢乙個點到沒到過,而是找乙個中間串出沒出現過,set一下就行了 include include include include include include include include include i...