1. 程式人生 > >Travelling Salesman Problem看法和我感覺不錯的解決思路

Travelling Salesman Problem看法和我感覺不錯的解決思路

最近看資料結構,看到了tsp問題,覺得很有趣,就去搜索了相關演算法,但是大多都是執行時間很久(我看幾個演算法演示結果的圖片,其實效果也不好,實際就不懂了),貪心演算法快但是效果最差。

我看過研究說蜜蜂能很好解決tsp問題,我們人也能在節點比較少的時候,很快找到一條不錯 的路徑,我覺得這是因為知道節點的前後位置,節點與節點的距離有很大關係,我看過幾個演算法都沒有用節點的位置這個條件(也就是座標這個條件,其實那些演算法我沒看過,只是看過原理,程式碼用c++寫的我根本看不下去 ),但是其實很多現實的tsp問題都有位置這個條件的,當年提出這個問題:有n個城市,一個推銷員要從其中某一個城市出發,唯一走遍所有的城市,再回到他出發的城市,求最短的路線。在解決這個問題的時候只關注每個點與另外點的距離,從來不關注位置。在我看來,如果把tsp看做物件,那麼加入位置這個條件那麼就變成一個例項,加入位置這個條件可以迅速找到一條比較好的路徑。

   按照上面的想法,我在自己電腦用c#編寫小程式測試2000個節點,沒有多執行緒,時間只花了三四秒,其中大部分是在生成座標,和各個節點的距離排序,到真正找路徑實際應該不到一秒,但是因為我程式設計基礎差,效果也達不到我的預期

 我的程式思路是這樣的

1.隨機生成n個座標;

2.計算每個點到其他點的距離,並從小到大排序,(程式時間基本都是耗在這裡,程式也基本很多時候要靠距離和位置來做出選擇)

3.隨機選一個起點作為起始點,並加入連結串列;

4.從連結串列獲取到最後一節點,根據這個節點(記做p),找到離這個節點最近的節點,記做closeP(有點類似貪心演算法,只不過多加幾個邏輯,這也是上面排序的原因),我們可以幾個邏輯判斷是否要連上closeP

1)如果closeP的最近兩個節點都是已經被連線的,那就判斷把closeP加入裡它最近的兩個節點合算還是直接和p連接合算

2)如果最近的一個節點已經連線

        3)如果最近的兩個節點都沒有連線,那麼就連上closeP,

4)等等其他。。。。

上面幾個邏輯還可以做細節優化

5.連上下個節點之前,要判斷有沒有這樣連線會不會穿越之前路線,如果穿越了(這就要座標計算了,那p節點半徑內的節點都拿來計算有沒有穿越,還沒加入連結串列的不算,,半徑可以通過節點的密度計算),那麼就把連結串列改下,比如穿越了a,b (a->b)兩個節點,那麼就把a之後的節點都反序,比如本來是,abcdef 就變成afedcb ,然後再通過b去連那個closeP,直到連上

迴圈 4~5 這樣所以節點都連上了,這樣一條路徑就找到了,然後再優化這條路徑,比如連結串列某個節點的離下一個節點距離大於座標密度,就根據一些邏輯優化,還有進行區域性最優化處理

這樣完之後基本一條比較好的路徑就出來了

我覺得如果實際問題不要求最優解又要時間快,我覺得這方法不錯,有一定概率碰到最優解最後我想說,這些都是我自己想象的結果,如果已經有出現這樣想法,或者我這個想法實際結果差強人意,那麼趕緊把這篇文章刪了,我寫的這邊文章的目的是我不想花時間去想這個問題了,因為結果可能不錯(可以幾秒內對上萬個節點查詢,路徑也滿足需求),也可能很差(很垃圾,找到的路徑和可接受的路徑差太多),但我根本無力驗證,不想浪費時間了,也希望如果有對演算法或者tsp問題有研究 的大神給我些建議