藍橋杯 BFS 八數碼問題(演算法筆記8)

2021-10-17 15:32:57 字數 995 閱讀 1996

題目中輸入初始狀態和目標狀態,返回最少的移動步數。

這與迷宮問題的最短路勁有些許相似,但這裡更多的是一種狀態的思考,本題涉及到「康托展開」這個特殊的雜湊函式。

但是,思路有了不代表能做對,因為ac還要考慮時間複雜度,空間複雜度問題,不過一般空間複雜度都沒太大的問題。那麼為什麼這裡說不能做對?這裡參考書上的圖

圖中畫紅色三角形的兩個狀態明顯是重複的狀態,也就是說這個狀態已經被搜尋過了。那麼從搜尋過的狀態再進行延伸,就會有很多重複的搜尋,浪費了大量的時間。那麼這題的關鍵就是如何去重,去重的方式可以參考爬樓梯問題的三部曲(普通遞迴,記憶性遞迴,動態規劃-遞推),也就是標記走過的點,這裡就是標記走過的狀態。

那麼這裡題目是乙個3*3的陣列,模擬迷宮問題,發現我們可以用座標的方式去做。但此時又有問題,座標標記狀態?這顯然不可行,因為隨著0的移動,這個棋盤的狀態是在改變的,而迷宮問題中,迷宮是固定的,點的標記只是為了回溯的時候方便(避免搜尋重複)。而且就算能按照之前的方式來做,那麼這個去重的過程,要涉及到的狀態n!×n!是否又太過於複雜?

這裡兩個點要考慮:①狀態怎麼表示?②能不能用座標做?③去重到底怎麼去重?

答案:陣列表示,能,用康托展開。

先說狀態怎麼表示:狀態只需要用一維陣列存放即可,陣列的大小就是n×n,其實這就是將從第二行開始的每一行直接放在第一行後面進行存放。

再說座標:按照一維陣列的存放狀態,那麼每n個就可以確定一行,列的確定只需要除n。舉個例子:假設在陣列中,我想知道5在3*3的格仔中處於哪個位置(以左上角為(0,0)),那麼6/3就是行x,6%3的就是列y,這裡的6是指5在陣列中第六個。這裡的解釋和書上**有些不同,具體實現我還沒試過。

最後是去重的康托展開:

康托展開的時間複雜度分析:

最後是**:

雙向BFS 八數碼問題

問題描述 在3 3的棋盤上,擺有八個棋子,每個棋子上標有1至8的某一數字。棋盤中留有乙個空格,空格用0來表示。空格周圍的棋子可以移到空格中。要求解的問題是 給出一種初始布局 初始狀態 和目標布局 目標狀態 找到一種最少步驟的移動方法,實現從初始布局到目標布局的轉變。例如 2 8 3 1 6 4 7 ...

BFS入門 八數碼問題

題目描述 初始狀態的步數就算1,哈哈 輸入 第乙個33的矩陣是原始狀態,第二個33的矩陣是目標狀態。輸出 移動所用最少的步數 input 2 8 3 1 6 4 7 0 5 1 2 3 8 0 4 7 6 5 output 思路 這道題bfs搜尋的每一步就是讓矩陣從乙個狀態變為另乙個狀態。所以我們用...

八數碼問題 雙向bfs

如 注釋的很清楚了 單向的還可以看看這個 以下是參考上面連線的雙向 include include include include include using namespace std int dr 2 queue int q1,q2 map int,int c1 記錄是否走過這個狀態,避免重複,...