第七章 最短路徑規劃
7.2.1 Bellman-Ford 演算法
說明演算法之前,我們必須假設一個網路圖,然後針對網路圖上的節點,運用此 一演算法求出最短路徑,藉以瞭解演算法的實際推演過程。所以我們假設有一網路圖 如圖 7.1 所示,其內共有 5 個網路節點,且節點 A 為目的點,並假設每一節點至少存 在一條路徑可到達目的點,由圖可知若每個節點最多只能經過一次,則從任一節點 i 到目的節點 A,最多包含有 h 個路段(h≦4;h=4 表經過所有節點後才到達節點 A),現 在我們就來解決從所有節點到節點 A 的最短路徑問題:
7 2
4 3 1 3 3
圖 7.1 五節點網路範例圖 7.2.1.1 參數定義:
1、令d 表節點 i 到節點 j 的路徑長度,若ij dij =∞表節點 i 到節點 j,沒有直接相連 的路徑。
2、令D 表節點 i 到節點 A(目的節點),所經過路段數目少於 h 個路段的最短路徑長ih 度。
7.2.1.2 演算法說明:
1、設定初值:
(1) 由網路圖得知所有的節點 i 到節點 j 之路徑長度,以d 表之。 ij
(2) 令Di0 =∞ 對所有的 i≠A。
B D
C E
A
(3) 令DAh =0 對所有的 h。
2、對所有的 h≧0,以下列公式計算Dih+1 之最小值
Dih+1 =m in j[dij+Dh,j Dih]對所有的 i≠A。
3、重複步驟 2,直至對所有的 i 均有 = ih+1 h
i D
D 之結果時則停止。
這個演算法首先找到一條路徑(One-arc)可到達的最短路徑,再找到兩條路徑 (Two-arc)可到達的最短路徑,如此一直找下去直到對所有的 i 均有Dih =Dih+1之結 果,或 h≧N-l(N 表所有節點數 )時停止。
7.2.1.3 範例說明:
我們運用圖 7.1 的網路圖以說明演算法的推演過程 : 1、設定初值:
DA0 = D1A =D2A =...=0 DB0 = DC0 = DD0 =...=∞
dBA =2;dCA =3;dBC =4;dDB =7;dEC =3;dDE =1;dED =3 dBD =dBE =dCB =dCD =dCE =dDC =dEB =∞(由網路圖得知)
2、求一條路徑(One-arc)可到達的最短路徑(h=1): D1A =0 (初值)
D1B =m in [dBA +D0A,dBC+DC0,dBD +DD0,dBE +DE0,DB0]
=m in
[
2+0,4+∞,∞+∞,∞+∞,∞]
=2DC1 =m in [dCA +D0A,dCB +DB0,dCD +DD0,dCE +DE0,DC0] =m in
[
3+0,∞+∞,∞+∞,∞+∞,∞]
=3D1D =m in [dDA +D0A,dDB +DB0,dDC +DC0,dDE +DE0,DD0] =m in
[
∞+0,7+∞,∞+∞,1+∞,∞]
=∞D1E =m in [dEA +D0A,dEB +DB0,dEC +DC0,dED +DD0,DE0]
=m in
[
∞+0,∞+∞,3+∞,3+∞,∞]
=∞3、求兩條路徑(Two-arc)可到達的最短路徑(h=2): DA2 =0 (初值)
DB2 =m in [dBA +D1A,dBC+D1C,dBD +D1D,dBE +D1E,D1B] =m in
[
2+0,4+3,∞+∞,∞+∞,2]
=2DC2 =m in [dCA +D1A,dCB +D1B,dCD +D1D,dCE +D1E,DC1]
=m in
[
3+0,∞+2,∞+∞,∞+∞,3]
=3DD2 =m in [dDA +D1A,dDB +D1B,dDC +DC1,dDE +D1E,D1D] =m in
[
∞+0,7+2,∞+3,1+∞,∞]
=9DE2 =m in [dEA +D1A,dEB +D1B,dEC +DC1,dED +D1D,D1E]
=m in
[
∞+0,∞+2,3+3,3+∞,∞]
=64、求三條路徑(Three-arc)可到達的最短路徑(h=3): DA3 =0 (初值)
DB3 =m in [dBA +DA2,dBC+DC2,dBD +DD2,dBE +DE2,DB2] =m in
[
2+0,4+3,∞+9,∞+6,2]
=2DC3 =m in [dCA +D2A,dCB +DB2,dCD +DD2,dCE +DE2,DC2]
=m in
[
3+0,∞+2,∞+9,∞+6,3]
=3DD3 =m in [dDA +D2A,dDB +DB2,dDC +DC2,dDE +DE2,DD2]
=m in
[
∞+0,7+2,∞+3,1+6,9]
=7DE3 =m in [dEA +D2A,dEB +DB2,dEC +DC2,dED +DD2,DE2]
=m in
[
∞+0,∞+2,3+3,3+9,6]
=65、下來求四條路徑(Four-arc)可到達的最短路徑(h=4),我們得到對所有節點都有
4 3
i
i D
D = 的結果 ,故演算法結束,各節點到節點 A 的最短路徑值即為D 的值 ,i4 演算法示意圖如圖 7.2 所示:
D1B =2 D1D =∞ DB2 =2 DD2 =9 2 2 7
D1A =0 3 DA2 =0 3
DC1 =3 D1E =∞ DC2 =3 DE2 =6 One-arc Two-arc
DB3 =2 DD3 =7 DB4 =2 DD4 =7 2 2
1 1 DA3 =0 3 3 DA4 =0 3 3
DC3 =3 DE3 =6 DC4 =3 DE4 =6
Three-arc Four-arc 圖 7.2 Bellman-Ford 演算法示意圖
B
A
C
D
E
A
B D
C E
B D
C E
A A
B D
C E
7.2.2 Dijkstra's 演算法
Dijkstra's 演算法的概念,是以目前最近的節點向外擴張,即將目前所剩節點 中,選出最短距離者加以擴張,每擴張一個節點,就比較「目前所剩節點到達目的節 點的距離」與「由此節點經過擴張節點再到達目的節點的距離」,取其最短者。所以 此演算法是以一個階段一個階段,漸漸增加路徑長度的方式,來求其最短路徑。現在 我們就來探討此一演算法,解決從所有節點到節點 A 的最短路徑的方式。
7.2.2.1 參數定義:
1、所有路徑長度都不為負值,且目的節點為 A。
2、N 表網路上所有節點數。
3、S 為一陣列,用以放置已處理完畢的節點。
4、T 為一陣列,用以放置尚未處理之節點 (與 S 互為補數 ) 5、D 及i D 表節點 i 或節點 j,到目的節點 A 的最短路徑。 j
6、d 表節點 i 到節點 j 的路徑長度,若 i=j 則ij d =0。若節點 i 到節點 j,沒有 ij
直接相連的路徑,則dij =∞。 7.2.2.2 演算法說明:
1、設定初值:
(1) 由網路圖得知所有的節點 i 至節點 j 之路徑長度,以d 表之。 ij (2) 令 S={A},T=N-S。
(3) 令DA =0。
(4) 令Dj =djA對所有的 j≠A。
2、在 T 中尋找下一個最近節點,並將此節點移至 S 內 Di =m in j∈T[D ]對所有的j i∈T 。
3.、T 不為空集合,則針對 T 內節點進行路徑長度修正,公式如下:
對所有的 j∈T ,Dj =m in j∈T[D,j dji +Di]。
4、重複步驟 2、3,直至 T 為空集合(或 S=N)為止。
7.2.2.3 範例說明:
我們仍然運用圖 7.1 的網路圖,來說明 Dijkstra's 演算法的推演過程:
1、設定初值:
N={A,B,C,D,E}
S={A} //A 為目的節點
T={B,C,D,E} //此為尚未處理的節點的集合
=0
DA ;D B =dBA =2;DC =dCA =3;DD =dDA =∞;DE =dEA =∞ 2、在 T 中找出距離 A 最近的節點 ,因D ,B D ,C D ,D D 中E D 為最小 , B 故選擇 B 節點
Di =m in j∈T[D ],j i∈T
=min{D ,B D ,C D ,D D }=min{2,3,∞,∞}=2 E 所以 i=B,將 B 節點移至 S 內
⇒S={A,B};T={C,D,E}
3、T 不為空集合,則針對 T 內節點進行路徑長度修正 公式:對所有的 j∈T ,Dj =m in j∈T[Dj,dji +Di] ⇒ DC =m in
[
DC,dCB +DB]
=m in[
3,∞+2]
=3DD =m in
[
DD,dDB +DB]
=m in[
∞,7+2]
=9DE =m in
[
DE,dEB +DB]
=m in[
∞,∞+2]
=∞4、在 T 中找出距離 A 最近的節點 ,因D ,C D ,D D 中E D 為最小 ,故 C 選擇 C 節點
Di =m in j∈T[D ],j i∈T
=min{D ,C D ,D D }= min{3,9,∞}=3 E 所以 i=C,將 C 節點移至 S 內
⇒ S={ A,B,C };T={ D,E }
5、T 不為空集合,則針對 T 內節點進行路徑長度修正 公式:對所有的 j∈T ,Dj =m in j∈T[D,j dji +Di]
⇒ DD =m in
[
DD,dDC +DC]
=m in[
9,∞+3]
=9DE =m in
[
DE,dEC +DC]
=m in[
∞,3+3]
=66、在 T 中找出距離 A 最近的節點,因D ,D D 中E D 為最小,故選擇 E 節點 E
T j
Di =m in ∈ [D ],j i∈T
=min{D ,D D }= min{9,6}=6 E 所以 i=E,將 E 節點移至 S 內 ⇒ S={ A,B,C,E };T={ D }
7、T 仍不為空集合,則針對 T 內節點進行路徑長度修正 公式:對所有的 j∈T ,Dj =m in j∈T[Dj,dji +Di]
⇒ DD =m in
[
DD,dDE +DE]
=m in[
9, 1+6]
=78、因 T 中只剩 D 節點(D 的值最小),所以只能選擇 D 節點 D Di =m in j∈T[D ],j i∈T = min{D }= min{7}=7 D
所以 i=D,將 D 節點移至 S 內 ⇒ S={A,B,C,E,D};T={}
9、T 為空集合則結束,此時D 內的值即為最短路徑值,其演算法示意圖如圖 i 7.3 所示。
DB =2 DD =∞ DB =2 DD =9 2 2 7
DA =0 DA =0
3 3
DC =3 DE =∞ DC =3 DE =∞
i = B i = C DB =2 DD =9 DB =2 DD =7 2 2
1 DA =0 3 3 DA =0 3 3
DC =3 DE =6 DC =3 DE =6
i = E i = D 圖例說明:目前計算路徑 最短路徑
圖 7.3 Dijkstra’s 演算法示意圖 7.2.3 Floyd's 演算法
Floyd's 演算法是計算所有點到所有點的最短路徑,其基本想法是認為:「如果 k 點是 i 到 j 上最佳路徑的一點,則 i 到 k 及 k 到 j 之路徑,均為最佳路徑」。所以其 路徑的求得係以「前一次 i 點到 j 點間的距離
(
Dk−1[ ]
i,j)
」與「前一次由 i 點經過 k 點到 j 點的距離(
Dk−1[ ]
i,k +Dk−1[ ]
k,j)
相比較,取其較小者。故有下列 Floyd's 方程式:B
A
C
D
E
A
B D
C E
B D
C E
A A
B D
C E
Dk
[ ]
i,j =m in(
Dk−1[ ]
i,j,Dk−1[ ]
i,k +Dk−1[ ]
k,j)
演算法步驟:
procedure Floyd((L[1..n,1..n]) array D[l..n,1..n]
D← L //D 儲存各點至其他各點之最短路徑值 for k← l to n do
for i← l to n do for j← l to n do
D[i,j] ← min(D[i,j],D[i,k] + D[k,j]) return