簡體   English   中英

在 Java 中使用動態編程解決 TSP

[英]Solving TSP using dynamic programming in Java

我在網上找到了很多討論這個和相關主題的資源,但我沒有找到任何真正幫助我知道從哪里開始實施這個解決方案的資源。

澄清一下,從0號城市開始,我需要每隔一個城市訪問一次,然后返回0號城市。

我有一個這樣的數組:

   0 1129 1417 1240 1951
1129    0 1100  800 2237
1417 1100    0 1890 3046
1240  800 1890    0 1558
1951 2237 3046 1558    0

在尋找最優路線的同時,我還需要找到沿途的最優部分路線。 例如,我從長度為 2 的路由開始,最后打印出如下內容:

S = {0,1}
C({0,1},1) = 1129

S = {0,2}
C({0,2},2) = 1417

S = {0,3}
C({0,3},3) = 1240

S = {0,4}
C({0,4},4) = 1951

然后我會轉到長度為 3 的路線,並打印如下內容:

S = {0,1,2}
C({0,1,2},1) = 2517
C({0,1,2},2) = 2229
and so on...

為了使其成為動態編程解決方案,我假設我應該保存任何 n 個節點之間的最短距離,而我認為這樣做的最佳方法是使用 Hashmap,其中的鍵是包含的每個節點的整數值在該路徑中,按升序(從節點 0>1>3>4 或 0>1>4>3 開始的路徑可以存儲為“134”),並且每個鍵都將保存一對可以存儲路徑順序作為一個列表,總距離作為一個整數。

在這一點上,我想我想計算距離為 2 的所有路徑,然后計算所有距離為 3 的路徑,然后取最小的幾個並使用哈希圖為每個路徑找到最短的路徑,並進行比較。

這看起來可行嗎? 還是我完全走錯了路?

你有點走上正軌了。 動態規划不是計算 TSP 的方法。 你有點接近的是計算最小生成樹。 這是一棵樹,使用盡可能短的邊總和連接所有節點。 有兩種經常使用的算法:Primm 算法和 Kruskal 算法。 它們產生類似於您的最佳部分路線列表的內容。 我建議你看看 Primm 的算法: https : //en.wikipedia.org/wiki/Prim%27s_algorithm

解決 TSP 的最簡單方法是找到最小生成樹,然后對樹進行預排序樹遍歷。 這為您提供了一個近似的旅行商解決方案,稱為三角不等式近似。 它保證不超過最佳 TSP 的兩倍,但可以更快地計算。 這個網頁解釋得相當好http://www.personal.kent.edu/~rmuhamma/Algorithms/MyAlgorithms/AproxAlgor/TSP/tsp.htm

如果您想要更優化的解決方案,則需要查看 Christofide 的方法,該方法更復雜。

你走在正確的軌道上。

我認為您正在了解這樣一個事實,即 DP 遞歸本身只告訴您每個 S 和 j 的最佳成本,而不是達到該成本的節點 處理這個問題的經典方法是通過“回溯”:例如,一旦您發現C({0,1,2,3,4},-) = 10000 ,您就會找出哪個節點達到了該成本; 假設它是 3。然后你找出哪個節點達到了C({0,1,2,3,4},3) 假設它是 1。然后你找出哪個節點達到了C({0,1,2,4},1) 假設它是 2,...等等。 這是經典方式,它避免了必須存儲大量中間數據。 對於狀態空間較小的 DP,沿途存儲所有這些優化器會更容易。 在您的情況下,您有一個指數級大的狀態空間,因此存儲所有這些優化器可能會很昂貴,但是您已經必須存儲同樣大的數據結構 ( C ),因此很可能您也可以存儲優化器。 您存儲一些最好的中間解決方案可以工作 - 那么如果回溯例程結果需要一個你沒有存儲的你可以用經典方式計算它 - 似乎合理,但我不確定它是否值得額外的編碼與純回溯方法。

澄清一點:你不是真的想“計算距離2的所有路徑,則所有距離3,...”,而是要枚舉大小為2,則所有大小為3,等所有集合仍然是指數級的,但沒有枚舉所有路徑那么糟糕。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM