A 演算法求第k短路徑

2022-08-05 14:09:10 字數 1195 閱讀 5864

a*演算法是一類貪心演算法,其可以用於尋找最優路徑。我們可以利用a*演算法來求第k短路徑。

一條路徑可以由兩部分組成,第一部分是乙個從出發到達任意點的任意路徑,而第二部分是從第一部分的末端出發,到終點的最短路徑。兩部分正好可以組成一條路徑,且每一條路徑都可以分解這兩部分(允許任意一部分為空)。因此當我們已知第一部分的路徑a時,設第二部分為b,我們可以嘗試預估完整的路徑a+b的費用(距離),我們將公式定義為:f(a)=g(a)+h(a)。其中g(a)表示第一部分a的已知長度,而h(a)表示路徑a到終點的預估最短距離,而f(a)表示路徑a的預估總費用。由於a*是貪心演算法,因此我們每次都會選擇預估總費用最低的路徑,並在進行拓展。

下面說明如何用a*演算法求解第k短路徑。首先我們需要計算從所有結點到終點的最短路徑(以終點為起點逆向跑最短路演算法)。之後我們維護乙個最小堆,在一開始將起點代表的路徑加入堆中。我們對路徑的評估採用a*的方式,由於每個結點到終點的距離已知,因此h(a)也是確定而非預估的。每次都從堆中取預估費用最小的路徑並在其上進行拓展(訪問相鄰的所有結點並建立新的路徑加入堆中,允許新路徑上出現重複結點),並將最小路徑從堆中移除。在上面過程中我們每次發現路徑的末尾是終點,則進行一次計數,直到計數為k,則我們找到了第k短路徑。

由於採用的是bfs方式擴充套件路徑,因此可以保證儲存在堆中的路徑都是不同的。每次找到的最短路徑必然是所以以殘留在堆中的路徑為字首的從起點到終點的最短路徑,可以知道依序找到的路徑1,2,...其費用必定非嚴格遞增。而第一次找到的路徑顯然是最短的。若前n-1次找到的路徑是前n-1短的,我們可以保證第n短的路徑的某個字首保留在堆中。若第n短的路徑與前n-1條找到的最短路徑的最長相同字首均為0,那麼可以保證這個字首必然是未被消耗的(所有的路徑的公共字首起點在一開始就加入了最小堆中)。而若第n短的路徑與第t短路徑有最長字首p,那麼兩條路徑t與路徑n的第p+1個結點互不相同,但是由於計算第t短路徑時,我們會將路徑n的p+1長字首建立並加入堆中,且一直到第n-1條路徑出堆,該p+1長字首都不會出堆,所以此時該字首依舊存在於最小堆中。故下一次找到的路徑是第n短的路徑。

下面說明時間複雜度,利用dijkstra演算法可以在o(|e|log2(|v|))時間複雜度內計算最短路徑。之後我們計算每次從堆中彈出完整路徑(從起點出發抵達終點的路徑)過程中最多有|v|條路徑被彈出(最短路徑不含環),且這過程中最多有|e|個結點被加入堆中。故堆中最多含有k|e|條路徑,因此總的時間複雜度為o(k*(|v|+|e|)log2(k|e|))+o(|e|log2(|v|))=o(k|e|log2(k|e|))。

演算法學習 A 求第k短路

a 是一種搜尋演算法,一般基於乙個估價函式f x g x h x 通過這個函式來進行有方向的搜尋以提高搜尋的效率 而不是bfs dfs那樣的盲目搜尋 其中g x 指從初始狀態到當前狀態的花費,h x 為當前狀態到終狀態的花費的估計值,以兩者之和來估計起始狀態到終狀態的總花費f x 在a 演算法中,通...

Yen演算法求K條最短路徑

眾所周知,dijkstra演算法可以求得一條最短路徑,但如果想求多條短路徑或者最短路徑有多條時,無法求得,需要用到yen演算法。源點c,終點h 1 通過最短路徑演算法dijkstra得到c到h的最短路徑 q 1 c e f h 5 2 偏離點c,e,f 3 c h,候選路徑 c d f h 8 4 ...

第K短路(A 演算法)

對於無向圖 spfa a 演算法 先用spfa求目標結點到各個結點的最短路徑 然後,取g x 為從初始結點到當前結點x的路徑長度,h x 為從x結點到目標結點的最短路徑長度,即h x 取dis x 即可,估價函式f x g x h x 對於有向圖 spfa a 演算法 顯然應將有向邊取反,然後求目標...