這方面的經典算法,有Dijkstra算法和Floyd算法。
下面簡單說一下基于Dijkstra算法略作小改動的一個算法。
假定,問題是這樣的:
我有N個點,每個點都與如果個別的點相連,是一個有向連接,且連接上有權重w_{i,j},可以為負。接著,我們要求每個節點i最多只能經過p_i次。
現在,給定起點和終點,求一條連接,其上的總權值最小。
算法的思路很簡單:
- 構造一個數組類型的數據結構,每個元素是從起點到當前位置的所有經過的節點,稱為路徑。
- 構造一個集合,將所有路徑的權重值和路徑兩段可以經過的次數的最小值成對放入并升序排列,如果多條路徑的權重值相同則將各自兩段節點的可經過次數的最小值累加起來。
- 構造一個目前所有走過的路徑的集合。
- 對所有路徑集合排序,找出權值最小的路徑,并將其從所有路徑集合中移除。
- 選擇上述最小權值路徑的最后一個節點,找出該節點的所有鄰點。
- 判斷該節點是否是終點,如果是終點,則將當前所有路徑集中的最小權重路徑的權重加上2中集合的所有負權值乘次數的總和,判斷是否比該路徑的權值小,如果更小,則將該路徑和備選最優路徑比較,將權值更小的選為新的備選最優路徑;否則,則和當前備選最后路徑比較,將權值更小的作為最優路徑輸出,結束循環。
- 查看上述鄰點,檢查其在當前路徑中出現的次數是否超過對應的最大經過次數,如果沒有超過,則復制當前路徑,并將該鄰點添加到最后,以當前路徑的權重值加上當前節點到該鄰點的連接的權重為新路徑的權重。
- 在2的集合中尋找當前路徑的權重對應的元素,將該元素中的總次數減一,如果減到0則從2中的集合中移除該權重對應的元素。
- 判斷上述鄰點是否為終點,如果不是終點則跳到X。
- 將上述過程中新生成的所有沒有到達終點的新路徑加到所有路徑集合中。
- 重復4。
從某種角度來說,這是一種深度優先搜索算法。
這樣的策略下,即便權重是負值,因為次優選擇如果加上所有可以加的負權重后依然不比當下最小權重更小,那么當下最小權重自然就是最終最小權重了。
這個算符當然還不是最優的,至少在某些情況下存在進一步優化的可能。
比如,假如每個節點都只允許通過一次,那么上面的策略就可以調整為,記錄每個節點是否已經被通過,所有路徑共享這一信息,而不是在每條路徑內自己做比較,這樣在搜索的時候可以優化很多,將搜索空間壓縮掉很多。
而如果權值不能為負數,那么備選最優的部分也可以跳過,因為次小權值加上一個非零實數,怎么都不會變成最小權重的。
事實上,還有一種大致可以將計算量減少一半的方案,就是從起點和終點同時開始以上述方法向外探索(注意對于有向圖來說,從終點開始的權值的取值方向和搜索方向是反向的),直到兩個搜索區域接觸,然后走一下備選最優路徑的選擇過程,直到沒有更優為止。
這套算法本身可以看做是一個不斷作圓向外推廣的過程,所以最開始的只從起點開始搜索的方案,需要走過的路徑如果看做一個圓的話,那么當我們從起點和終點同時開始搜索的時候,就是兩個等大的圓相切。前者的搜索空間正比于r2,r為起點和終點的距離,而后者的搜索空間只要(r2)/2。
當然,實際的問題中當然不是圓,所以這只是一個大致的類比。
總之,雙源頭的搜索是更優的方案,而如果問題本身有一定的限制,比如每個節點只能通過一次或者沒有負權重,那么就可以有更加高效的方案。
上面談了下經典的尋找最短路徑的算法。
這里再深入一下。
我們就假定每個節點只能通過一次,且每條邊的權重都大于零。
那么,一個N個節點構成的網,那么上述算法的計算量大約就是O(k N^2)的量級,其中k是平均鄰點數。
顯然,如果不用高級算法的話,這個極限是很難突破的了。
那么,如果我們用一些高級算法,比如蟻群算法、退火算法和遺傳算法呢?
以1000個節點的TSP問題為例,在1000個節點中選擇一條閉合路徑鏈接所有節點,且要求這條路徑最短。
通常的算法,基本就是上面所說,計算量在O(N^3)的量級(這里沒有明確的鄰點概念,所以k = N)。
然后,使用蟻群算法、退火算法和遺傳算法后,有趣的情況出現了:
恰當配置下,蟻群算法最優,遺傳算法結果最差。
但蟻群算法收斂慢,且容易陷入局部極有陷阱,這方面遺傳算法好。
然后,我們做一個優化:將遺傳算法得到的結果,和蟻群算法一樣做權值統計,此后的變異不是完全隨機的變異,而是以權值統計出的權重作為幾率的基礎,來做變異。
這樣的結果就好了很多。
再進一步,和退火算法一樣,我們引入系統溫度,基因池分為兩部分,一部分是按照每個基因的適應度作為幾率做篩選留下的“優質”基因,一部分是隨機抽選留下的基因,可能優也可能差。這兩部分基因根據一定的比例混合,而這個比例是溫度的函數,溫度則有算法給出的結果來控制。
這么三種算法混合后,我們很驚訝地發現,混合算法明顯可以找到更加優的結果,但缺點也很顯然:太慢了——當然,還是比O(N^3)要好的。
從這里我們也可以看出一些好玩的東西來:
演化是一種很尷尬的存在,首先它不能堅定地沿著當下最優的方向走,這樣可能會走入局部極優陷阱而走不出來;另一方面,又不能都是隨機行走,這樣的結果太糟糕。只有兩者的恰當結合,才能有更好的發展。
通過本協議,您可以分享并修改本文內容,只要你遵守以下授權條款規定:姓名標示 、非商業性、相同方式分享。
具體內容請查閱上述協議聲明。
本文禁止一切紙媒,即印刷于紙張之上的一切組織,包括但不限于轉載、摘編的任何應用和衍生。網絡平臺如需轉載必須與本人聯系確認。
如果喜歡簡書,想要下載簡書App的話,輕戳這里~~
<small>私人推薦訂閱專題:《有意思的文章》、《嚴肅碼匠圈》</small>