第二屆“演算法控”馬拉松程式設計競賽 解題思路

shǎ崽發表於2012-12-26

前陣子在微博上看到了這個活動 第二屆“演算法控”馬拉松程式設計競賽 解一個NP-hard問題,比賽形式不錯,還有獎勵,果斷搞之
題目給出地鐵線路圖和換乘的站點以及等待時間,要求用最短的時間遍歷地鐵所有的站點。
這很像經典的TSP(Traveling Salesman Problem)問題,這個模型已經有很多智慧演算法可以解決了,我挑選了蟻群演算法,具體思路如下:

  1. 首先要把地鐵轉化成TSP的模型,由於地鐵有逆行正行還要考慮換乘時間,每個站點會有好幾個狀態(在幾號線,目前乘坐地鐵的方向),所以要進行拆點
    • 首先把每個站點拆成正行a1,a2...an和逆行的b1,b2...bn,ai和bi(1<=i<=n)是雙向,時間為等待時間;ai可以到ai+1,bi+1可以到ai,時間就是地鐵的行駛時間。
    • 由於上述拆點,每個換乘站都會被拆成好多個點,換乘點之間再連雙向邊,時間為換乘時間+等待時間
    • 到此,我們的新圖就建立出來了,由於拆點並且換乘點被拆成了好多個,極限情況下的點數 = (換乘站數量 * 地鐵線數量 + 地鐵站數量 - 換乘站數量) * 2。也就是N = (70 * 20 + 300 - 70) * 2 = 3260
  2. 在拆點的過程中要將拆出來的點和原來的點的對應關係儲存起來,一來用於最後輸出解,二來我們遍歷的不是拆點後的每個點,而是實際的每個地鐵站
  3. 接下來算一個全域性最短路,求出每個點之間的最短路
  4. 模型轉化出來之後就可以用蟻群演算法(蟻群演算法的資料網上很多,就不再重複了)搞了,迭代一次的複雜度是螞蟻數量 * 地鐵站數量 * 拆點後的數量

比賽期間調了一下引數之後跑出的結果還是沒能達到很好的效果,於是我想著縮點:

將地鐵的換乘站和起止點標記為keyStation,然後將每條地鐵線中的keyStation之間的一些點縮成2個點,如地鐵線a<->b<->c<->d<->e<->f<->g,其中a和g是keyStation,那麼就可以縮點縮成a->f'->g和a<-b'<-g,然後a到f'的距離就是a到f的距離,並且f'這個點直接代表bcdef這5個站點,b'類似
雖然這個方法最後並沒有優化成更好的結果,不過可能是隨機演算法的不穩定的問題,anyway由於模型的特殊性,這個縮點方法可以很大程度的縮小地圖

程式碼發出來格式亂了,有興趣的朋友可以直接問我要notonlysuccess[at]gmail[dot]com
P.S 還差9兩銀子才能買一本圖靈社群裡看中的一本書,由於沒辦法直接用錢兌換銀子,求各路有銀子的大俠捧個錢場~~

相關文章