要解決的問題:
給定乙個迷宮,此迷宮中有且僅有乙個入口和出口,其中設有若干檢查點,要求從入口開始,經過所有檢查點後到達出口所需的最短路徑。其中路徑中允許多次經過入口或出口或某檢查點,但路徑的開始和結尾必須分別是入口和出口。更形象一點就是要把圖中所有的寶藏找出來帶出去的問題。
連設計演算法+寫演算法實現的**+編寫**和製作演示動畫,花費了四天時間,還是小有收穫的趕腳。演算法的核心描述就是先假設已經有乙個最優路徑,然後插入乙個新的檢查點時,如何使插入導致的路徑增量最小。
這種先假設存在最優路徑然後再在這條假設的路徑中插入新的結點的思想其實就是貪心演算法,出現在很多演算法當中,並且十分行之有效,其基本模型就是持有兩個關鍵集合,根據條件改變集合元素來動態規劃集合中元素的組織方式。此題中的尋寶演算法十分類似於貨郎擔問題,區別在於,貨郎在尋找旅行路線時不能經過已經走過的城市,且最終要回到出發點,而這裡的模型是可以經過已經走過的城市,但最終不是要回到出發點,而是以達到乙個指定點結束。但本質上都需要兩個動態集合來儲存這些代表地點的結點。貨郎擔問題相對於此問題的簡單之處表現在其不重複的特點上,因為不重複,所以每個結點必有單前驅與單後繼,集合中元素都不相同,組合起來就很簡單。而此問題由於可以多次經過同乙個節點,所以在一條路徑上就存在多個相同的結點,這就導致了同一結點有多前驅或多後繼的問題。本問題解決的關鍵就是要解決這種多前驅與多後繼的問題,也就是要決定同一結點如何在集合中表現出多種身份的方式。我在設計此演算法時,到此便知道這就是問題的核心了,最終想到的辦法就是為多前驅或多後繼的結點建立多個虛擬結點,這些虛擬結點實質上共享同乙個位置,但卻分別有著不同的前驅與後繼,因此可以構成一條完成的路線。然後問題就轉移到如何在兩個集合中標識這些虛擬結點的身份了。剩下的問題不再是難題,除了需要計算在插入新結點時如何查詢最優插入區間、如何計算插入後帶來的代價增量、如何決定是採用正常插入模式還是採用建立新的虛擬結點的插入方式等問題了。其中用到了演算法導論一書中介紹的「三角不等式(兩邊之和大於第三邊,兩邊之差小於第三邊)」原理來計算和比較代價增量。
最後,如設計演算法時所描述,這其實是乙個np完全問題,無法驗證它是最優的,插入時存在穩定性改變的問題,但絕大多數情況下,得到的結果就是我們想要的最優結果。同時,整個尋路過程中,bfs演算法的時間複雜度為o(logn),其中包括前向找出口的logn的時間和回退的logn的時間以及路徑方向整理的logn的時間,這個總的時間複雜度雖然不算特別大,但卻經常需要計算兩點間的最短路徑,而在很多情況下,需要重複計算上一次所得的結果。因此在演算法中適時儲存和處理中間結果將能夠大大提高演算法的時間效能。
最終的執行結果如圖所示:
最普通的貨郎擔問題實現
題目描述 n個頂點,從1頂點開始出發走遍所有結點回到1頂點最小路程。最普通的貨郎擔問題實現 上圖輸入 41 3 1 1 4 7 2 1 8 2 3 5 2 4 1 3 1 7 3 2 2 3 4 6 4 1 2 4 2 5 4 3 3 0 0 0 二 稍微題目修改下,從頂點1開始不用全部走遍各個結點...
迷宮最短路徑問題
問題描述 給定乙個迷宮和乙個起點乙個終點,求起點到終點的最短路徑長度。sample input 說明 5行5列的迷宮,為牆,為路,起點為 0,3 終點為 4,4 sample output 若不可達輸出 1 解答 用bfs的方法,借助乙個佇列實現。1 include2 include3 includ...
迷宮問題 最短路徑問題
給定乙個 n nn n 的二維陣列,如下所示 int maze 5 5 它表示乙個迷宮,其中的1表示牆壁,0表示可以走的路,只能橫著走或豎著走,不能斜著走,要求程式設計序找出從左上角到右下角的最短路線。資料保證至少存在一條從左上角走到右下角的路徑。輸入格式 第一行包含整數 n。接下來 nn 行,每行...