尋找最短路徑

這方面的經典算法,有Dijkstra算法和Floyd算法。

下面簡單說一下基于Dijkstra算法略作小改動的一個算法。


假定,問題是這樣的:

我有N個點,每個點都與如果個別的點相連,是一個有向連接,且連接上有權重w_{i,j},可以為負。接著,我們要求每個節點i最多只能經過p_i次。
現在,給定起點和終點,求一條連接,其上的總權值最小。

算法的思路很簡單:

  1. 構造一個數組類型的數據結構,每個元素是從起點到當前位置的所有經過的節點,稱為路徑。
  2. 構造一個集合,將所有路徑的權重值和路徑兩段可以經過的次數的最小值成對放入并升序排列,如果多條路徑的權重值相同則將各自兩段節點的可經過次數的最小值累加起來。
  3. 構造一個目前所有走過的路徑的集合。
  4. 對所有路徑集合排序,找出權值最小的路徑,并將其從所有路徑集合中移除。
  5. 選擇上述最小權值路徑的最后一個節點,找出該節點的所有鄰點。
  6. 判斷該節點是否是終點,如果是終點,則將當前所有路徑集中的最小權重路徑的權重加上2中集合的所有負權值乘次數的總和,判斷是否比該路徑的權值小,如果更小,則將該路徑和備選最優路徑比較,將權值更小的選為新的備選最優路徑;否則,則和當前備選最后路徑比較,將權值更小的作為最優路徑輸出,結束循環。
  7. 查看上述鄰點,檢查其在當前路徑中出現的次數是否超過對應的最大經過次數,如果沒有超過,則復制當前路徑,并將該鄰點添加到最后,以當前路徑的權重值加上當前節點到該鄰點的連接的權重為新路徑的權重。
  8. 在2的集合中尋找當前路徑的權重對應的元素,將該元素中的總次數減一,如果減到0則從2中的集合中移除該權重對應的元素。
  9. 判斷上述鄰點是否為終點,如果不是終點則跳到X。
  10. 將上述過程中新生成的所有沒有到達終點的新路徑加到所有路徑集合中。
  11. 重復4。

從某種角度來說,這是一種深度優先搜索算法。

這樣的策略下,即便權重是負值,因為次優選擇如果加上所有可以加的負權重后依然不比當下最小權重更小,那么當下最小權重自然就是最終最小權重了。


這個算符當然還不是最優的,至少在某些情況下存在進一步優化的可能。

比如,假如每個節點都只允許通過一次,那么上面的策略就可以調整為,記錄每個節點是否已經被通過,所有路徑共享這一信息,而不是在每條路徑內自己做比較,這樣在搜索的時候可以優化很多,將搜索空間壓縮掉很多。

而如果權值不能為負數,那么備選最優的部分也可以跳過,因為次小權值加上一個非零實數,怎么都不會變成最小權重的。

事實上,還有一種大致可以將計算量減少一半的方案,就是從起點和終點同時開始以上述方法向外探索(注意對于有向圖來說,從終點開始的權值的取值方向和搜索方向是反向的),直到兩個搜索區域接觸,然后走一下備選最優路徑的選擇過程,直到沒有更優為止。

這套算法本身可以看做是一個不斷作圓向外推廣的過程,所以最開始的只從起點開始搜索的方案,需要走過的路徑如果看做一個圓的話,那么當我們從起點和終點同時開始搜索的時候,就是兩個等大的圓相切。前者的搜索空間正比于r2,r為起點和終點的距離,而后者的搜索空間只要(r2)/2。

當然,實際的問題中當然不是圓,所以這只是一個大致的類比。

總之,雙源頭的搜索是更優的方案,而如果問題本身有一定的限制,比如每個節點只能通過一次或者沒有負權重,那么就可以有更加高效的方案。


上面談了下經典的尋找最短路徑的算法。

這里再深入一下。

我們就假定每個節點只能通過一次,且每條邊的權重都大于零。

那么,一個N個節點構成的網,那么上述算法的計算量大約就是O(k N^2)的量級,其中k是平均鄰點數。

顯然,如果不用高級算法的話,這個極限是很難突破的了。

那么,如果我們用一些高級算法,比如蟻群算法、退火算法和遺傳算法呢?


以1000個節點的TSP問題為例,在1000個節點中選擇一條閉合路徑鏈接所有節點,且要求這條路徑最短。

通常的算法,基本就是上面所說,計算量在O(N^3)的量級(這里沒有明確的鄰點概念,所以k = N)。

然后,使用蟻群算法、退火算法和遺傳算法后,有趣的情況出現了:

恰當配置下,蟻群算法最優,遺傳算法結果最差。

但蟻群算法收斂慢,且容易陷入局部極有陷阱,這方面遺傳算法好。

然后,我們做一個優化:將遺傳算法得到的結果,和蟻群算法一樣做權值統計,此后的變異不是完全隨機的變異,而是以權值統計出的權重作為幾率的基礎,來做變異。

這樣的結果就好了很多。

再進一步,和退火算法一樣,我們引入系統溫度,基因池分為兩部分,一部分是按照每個基因的適應度作為幾率做篩選留下的“優質”基因,一部分是隨機抽選留下的基因,可能優也可能差。這兩部分基因根據一定的比例混合,而這個比例是溫度的函數,溫度則有算法給出的結果來控制。

這么三種算法混合后,我們很驚訝地發現,混合算法明顯可以找到更加優的結果,但缺點也很顯然:太慢了——當然,還是比O(N^3)要好的。

從這里我們也可以看出一些好玩的東西來:

演化是一種很尷尬的存在,首先它不能堅定地沿著當下最優的方向走,這樣可能會走入局部極優陷阱而走不出來;另一方面,又不能都是隨機行走,這樣的結果太糟糕。只有兩者的恰當結合,才能有更好的發展。


本文遵守創作共享CC BY-NC-SA 4.0協議

通過本協議,您可以分享并修改本文內容,只要你遵守以下授權條款規定:姓名標示非商業性相同方式分享
具體內容請查閱上述協議聲明。

本文禁止一切紙媒,即印刷于紙張之上的一切組織,包括但不限于轉載、摘編的任何應用和衍生。網絡平臺如需轉載必須與本人聯系確認。


如果喜歡簡書,想要下載簡書App的話,輕戳這里~~
<small>私人推薦訂閱專題:《有意思的文章》《嚴肅碼匠圈》</small>

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,572評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,071評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,409評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,569評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,360評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,895評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,979評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,123評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,643評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,559評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,742評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,250評論 5 356
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,981評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,363評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,622評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,354評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,707評論 2 370

推薦閱讀更多精彩內容