廣度優先搜尋(二)

2022-07-17 04:06:13 字數 1762 閱讀 5001

【例5】 8數碼難題

【問題描述】:

在 3 * 3 的棋盤上,擺有八個棋子,每個棋子上標有 1 至 8 的某一數字。棋盤中留有乙個空格。空格周圍的棋子可以移到空格中。要求解的 問題是,給出一種初始布局 [ 初始狀態 ] 和目標布局 [ 目標狀態 ] ,找到一種移動的方法,實現從初始布局到目標布局的轉變。

【輸入格式】

輸入由兩行組成,每行9個數,分別表示初始狀態和目標狀態:

【輸出格式】

有若干行,第一行表示最小步數 ,接下來的每行輸出一步的狀態,如果在6步內無法達到目標狀態,輸出「no solution!」。

【輸入輸出樣例】

輸入檔名: 8num.in

輸出檔名:8num.out

【問題分析】:

這是一道典型的搜尋題目,搜尋產生的結點可以達到9!,再加上判重,如果不優化的話,耗時嚴重,關於廣搜得優化我們後面的學習中再作討論,本題只要求輸出6步以內可以達到的目標,所以使用一般的廣搜即可解決。問題是,如何在擴充套件結點的同時計算出已經走的步數,而不是找到目標狀態後再逆序跟蹤輸出步數和步驟?

兩種方法,一種是在佇列中增加乙個域,來記錄擴充套件出當前狀態用的步數,該步數是由它的父節點步數加1得到。

另一種方法是雙尾指標法。廣搜是按層次搜尋的,每搜完一層,即可視為走完一步,所以,只要記錄下來當前搜尋了多少層即可。我們使用tail2記錄當前擴充套件層最後乙個節點在佇列中的位置,當head指向tail2並且擴充套件完tail2,說明完成一層的搜尋,此時step+1,並且tail2指向tail,也就是擴充套件出的新的一層的尾結點。

記錄步數的廣搜演算法框架如下:

1

program bfs;

2初始化,初始狀態存入open 表;

3 佇列首指標head:=0;尾指標 tail:=1;tail2:=1; step:=1;

4repeat

5指標head後移一位,指向待擴充套件結點;

6for i=1

to max do

7begin

8if 子結點符合條件 then

9begin

10if新結點是目標結點 then 輸出 else

11if新結點與原已產生結點不重複 then

tail 指標增1,把新結點存入列尾;

12end

; 13

end;

14if head=tail2 then begin inc(step);tail2:=tail;end;

15until(head>=tail);

另外我們需要考慮如何記錄數碼狀態,可以使用3*3的二維陣列,也可以使用長度為9的字串。一般使用陣列記錄,實現起來比較簡單,但是判重的時候比較麻煩,如果使用9維布林陣列來判重,那麼需要很大的儲存空間,不過速度會較快,如果使用字串來記錄,難以用布林陣列來判重,所以判重耗時巨大,但是字串可以直接比較並且本題的規模也不大,只要判斷6步以內是否能夠達到目標狀態,所以我們不妨使用字串s來記錄數碼狀態,用p來記錄s中0的位置,0與其他數字的交換最多有四種情況:

與上方的數字交換則把p與p-3位置的字元交換位置;

與右邊的數字交換則把p與p+1位置的字元交換位置;

與下方的數字交換則把p與p+3位置的字元交換位置;

與左邊的數字交換則把p與p-1位置的字元交換位置;

注意特殊情況下,當p=4或7時,0不能與左邊數字交換,當p=3或6時,0不能與右邊數字交換,另外,所有的交換位置都不能超過1~9範圍。

搜尋演算法_8數碼難題1

ayyzoj p1461

訓練二 廣度優先搜尋

例1.hdu 1548 題意有人想乘電梯從 a樓到達b樓,電梯 只有兩種情況,上和下 給定電梯的上下固定樓 求從a到達b的最少移動次數?hdu1548 每層電梯有乙個數字表示該層可以移動的層數 include include include define n 201 using namespace ...

搜尋 廣度優先搜尋

廣度優先搜尋一層一層地進行遍歷,每層遍歷都是以上一層遍歷的結果作為起點,遍歷乙個距離能訪問到的所有節點。需要注意的是,遍歷過的節點不能再次被遍歷。class solution,int shortestpathbinarymatrix vectorint grid length return 1 cl...

廣度優先搜尋

include include include include using namespace std struct node 圖頂點結構定義 typedef struct node graph 圖形的結構新型態 struct node head 9 圖形頂點陣列 int visited 9 遍歷標...