Travelling Salesman Problem(旅行商問題)
旅行商問題(TSP):給定一組城市和每對城市之間的距離,找到每個城市只訪問一次並返回起點的最短路徑。
注意Hamiltonian Cycle(哈密頓迴路)和TSP之間的區別。 Hamiltoninan Cycle問題是找出是否存在一次訪問每個城市一次的旅行。 在這裡我們知道Hamiltonian Cycle存在(因為graph
是完整的)並且實際上存在許多這樣的Cycle,問題是找到最小權重的Hamiltonian Cycle。
例如,請考慮下圖中所示的graph
。 圖中的TSP路徑是1-2-4-3-1
。 這次旅行的費用是10 + 25 + 30 + 15
,即80
。
這是一個非常著名的NP
樸素的解決方案:
- 1)將城市1視為起點和終點。
- 2)生成所有
(n-1)!
城市的排列。 - 3)計算每個排列的路徑長度並跟蹤最小路徑長度的排列。
- 4)返回最後的最小路徑排列。
// implementation of traveling Salesman Problem
int travllingSalesmanProblem(int graph[][V], int s)
{
// store all vertex apart from source vertex
vector<int> vertex;
for (int i = 0; i < V; i++)
if (i != s)
vertex.push_back(i);
// store minimum weight Hamiltonian Cycle.
int min_path = INT_MAX;
do {
// store current Path weight(cost)
int current_pathweight = 0;
// compute current path weight
int k = s;
for (int i = 0; i < vertex.size(); i++) {
current_pathweight += graph[k][vertex[i]];
k = vertex[i];
}
current_pathweight += graph[k][s];
// update minimum
min_path = min(min_path, current_pathweight);
} while (next_permutation(vertex.begin(), vertex.end()));
return min_path;
}
這個解法在之前的Hamiltoninan Cycle中也提到過,對於較大的n
來說,這種做法當然是不可取的。這個問題可以通過動態規劃的方法來解決。
對於給定的頂點集合為{1,2,3,4 ......}
。我們將1
視為輸出的起點和終點。對於每個其他頂點i
(除1
之外),我們找到一條到i
的最短路徑,其中1
為起點,i
為結束點,所有頂點恰好出現一次。假設這條路徑的總長度為cost(i)
,則我們最後的路徑長度將是cost(i)+dist(i,1)
,其中dist(i,1)
是從i
到1
的距離。最後,我們返回所有[cost(i)+dist(i,1)]
值的最小值。到目前為止一切都看起來很簡單,現在的問題就變成了如何獲得cost(i)
?
我們可以使用動態規劃來計算cost(i)
。首先我們定義表示對於集合中每個頂點i
來說,從1
開始到i
結束的最短路徑長度。我們從大小為2
的所有子集開始,並計算所有子集的,其中是子集,然後我們計算大小為3
的所有子集的,依此類推。請注意,每個子集中必須存在1
。
如果的大小為2,那麼必須是,
否則,如果的大小大於2,其中屬於,且。
對於一組大小為n
的集合,我們考慮n-2
個子集,每個子集的大小為n-1
,使得所有子集中都沒有第n
個數。
使用上述遞迴關係,我們就可以寫出相應的動態規劃的程式碼。最多有個子問題,每個子問題需要線性時間來解決。因此總執行時間為。時間複雜度遠小於,但仍然呈指數級。所需空間也是指數級的。因此,即使對於稍高數量的頂點,這種方法也是不可行的。
int n=4;
int dist[10][10] = {
{0,20,42,25},
{20,0,30,34},
{42,30,0,10},
{25,34,10,0}
};
int VISITED_ALL = (1 << n) -1;
int dp[16][4];
int cost(int mask,int pos)
{
if (mask == VISITED_ALL){
return dist[pos][0];
}
if (dp[mask][pos] != -1){
return dp[mask][pos];
}
//Now from current node, we will try to go to every other node and take the min ans
int ans = INT_MAX;
//Visit all the unvisited cities and take the best route
for (int city = 0; city < n; city++)
{
if ((mask & (1 << city)) == 0)
{
int newAns = dist[pos][city] + cost(mask | ( 1 << city), city);
ans = min(ans, newAns);
}
}
return dp[mask][pos] = ans;
}
我們稍微解釋一下上面這個程式碼,其中mask
表示我們訪問的節點,假設我們有4
各節點,如果mask=1111
的話,表示cdba
都訪問過了,也就是mask=1<<4 - 1=1111
;如果mask=0001
,表示只有a
訪問過了,以此類推。那麼我們就可以通過(mask & (1 << city)) == 0
判斷當前節點是不是被訪問過。例如,對於節點a
city = 0
1 << 0 = 0001
mask = 0001
mask & (1 << city) == true
如果當前的節點沒有被訪問過,我們才進行後續操作。也就是遞迴呼叫cost
。其中mask | ( 1 << city)
表示對city
進行訪問,例如
city = 0
1 << 0 = 0001
mask = 0000
mask | (1 << city) = 0001
最後我們只要取每次結果的最小值即可。
前面已經說過,這個問題沒有多項式時間的解決方法。但是有一些近似的演算法來解決這個問題。僅當問題例項滿足Triangle-Inequality(三角不等式)時,近似演算法才有效。
三角不等式:從i
到達頂點j
的最遠路徑總是直接從i
到達j
,而不是通過其他一些頂點k
(或頂點),即dist(i,j)
總是小於或等於到dist(i,k) + dist(k,j)
。三角不等式在許多實際情況中都有。
當cost
函式滿足三角不等式時,我們可以為TSP設計一個近似演算法,該演算法返回一個最短路徑長度不超過最優解的兩倍。我們的想法是使用最小生成樹(MST)。以下是基於MST的演算法。
- 1)以
1
為起點和終點。 - 2)使用
Prim
演算法,以1
為根構造MST
。 - 3)列出在構造的
MST
的前序步行中訪問的頂點,並在末尾新增1
。
考慮以下示例。圖中顯示了以1
為根構造的MST。 MST的前序遍歷為1-2-4-3
。最後新增1
給出1-2-4-3-1
,這是該演算法的輸出。
在這種情況下,近似演算法產生最佳路徑,但它可能無法在所有情況下產生最佳路徑。這個演算法如何近似?上述演算法產生的輸出路徑絕不會超過最佳路徑的兩倍。讓我們看看上述演算法如何保證這一點。
在理解這個問題之前,我們首先要知道full walk。full walk是指在先序遍歷訪問樹的全部節點時列出的所有走的步驟。上面樹的full walk將是1-2-1-4-1-3-1
。
- 1)TSP絕不低於MST。 (MST的定義是,它是連線所有頂點的最小生成樹)。
- 2)full walk的最多是MST的兩倍(MST的每個邊緣最多訪問兩次)
- 3)上述演算法的輸出小於full walk。在上面的演算法中,我們列印前序遍歷作為輸出。在前序遍歷中,full walk的兩個或更多個邊緣被單個邊緣替換。例如,
2-1
和1-4
被2-4
代替。因此,如果圖形遵循三角形不等式,那麼這總是正確的。
從上述三個陳述中,我們可以得出結論,近似演算法產生的輸出結果絕不會超過最佳解決方案的兩倍。
我們已經討論了一個非常簡單的2倍近似演算法來解決旅行商問題。對於該問題還有其他更好的近似演算法。例如,Christofides
演算法是1.5倍近似演算法。
reference:
相關推薦
Travelling Salesman Problem(旅行商問題)
旅行商問題(TSP):給定一組城市和每對城市之間的距離,找到每個城市只訪問一次並返回起點的最短路徑。 注意Hamiltonian Cycle(哈密頓迴路)和TSP之間的區別。 Hamiltoninan Cycle問題是找出是否存在一次訪問每個城市一次的旅行。 在
HDU 3001 Travelling:TSP(旅行商)
sta init using 多少 b- upd eof == als 題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=3001 題意: 有n個城市,m條雙向道路,每條道路走一次需要花費路費v。你可以將任意一個城市作為起點出
PAT (Advanced Level) Practice 1150 Travelling Salesman Problem (25 分)
The "travelling salesman problem" asks the following question: "Given a list of cities and the distances between each pair of cities, what is the shor
1150 Travelling Salesman Problem (25 分)(cj)
1150 Travelling Salesman Problem (25 分) The "travelling salesman problem" asks the following question: "Given a list of cities and the di
PAT 1150 Travelling Salesman Problem (25 分)
The "travelling salesman problem" asks the following question: "Given a list of cities and the distances between each pair of cities, what
【笨方法學PAT】1150 Travelling Salesman Problem (25 分)
一、題目 The "travelling salesman problem" asks the following question: "Given a list of cities and the distances between each pair of cities, what is
【HDU 5402】Travelling Salesman Problem(構造)
被某題卡SB了,結果這題也沒讀好。。。以為每個格子可以有負數就當搜尋做了,怎麼想也搜不過去,後來發現每個格子是非負數,那麼肯定就是構造題。 題解如下: 首先如果nn為奇數或者mm為奇數,那麼顯然可以遍歷整個棋盤。 如果n,mn,m都為偶數,那麼講棋盤黑白染色,假設(
2-opt求解TSP(旅行商)問題的python實現
2-opt其實是2-optimization的縮寫,簡言之就是兩元素優化。也可以稱作2-exchange 。(摘自百度百科) 這個一種隨機性演算法,基本思想就是隨機取兩個元素進行優化,一直到無法優化為止。在小規模TSP問題上,2-opt無論從效率還是效果上都優於
TSP(旅行商問題)-狀壓dp
給定n個點(0...n - 1)的帶權有向圖,出從0出發經過每點恰好一次再回到的0,求所經過的邊的總權值的最小值 n<=15,d(i, j) < 1000 方程為:dp[S][v] = min(dp[S + u][u], map[v][u]) dp[S][v]指
演算法課堂實驗報告(五)——python回溯法與分支限界法(旅行商TSP問題)
python實現回溯法與分支限界 一、開發環境 開發工具:jupyter notebook 並使用vscode,cmd命令列工具協助程式設計測試演算法,並使用codeblocks輔助編寫C++程式 程式語言:python3.6 二、實驗目標 1. 請用回溯法求對稱的旅
HDU 5402 Travelling Salesman Problem
algorithm else panel ati cin display eight etc maximum Problem Description Teacher Mai is in a maze with n rows and m columns.
ZOJ 1457 Prime Ring Problem(dfs+剪枝)
line alt sent math ica scanf 素數 n) div ?? Prime Ring Problem Time Limit: 10 Seconds Memory Limit: 32768 KB A ring is compose o
Hotaru's problem(hdu5371+Manacher)多校7
uri ems sample onos none mes ted pro ron Hotaru‘s problem Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Jav
HDU 5402(Travelling Salesman Problem-構造矩陣對角最長不相交路徑)
2.7 sample sum tro 長城 2.3 owin trac cal Travelling Salesman Problem Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 65536/
hdu5402:Travelling Salesman Problem
.... pat man 。。 scan oos 沒有 columns ext Travelling Salesman Problem 2017-09-01 Problem Description Teacher Mai is in a maze with n r
P1832 A+B Problem(再升級)
using 輸出格式 algorithm 一行 題目 -a scanf 問題 mes P1832 A+B Problem(再升級) 題目背景 ·題目名稱是吸引你點進來的 ·實際上該題還是很水的 題目描述 ·1+1=? 顯然是2 ·a+b=? 1001回看不謝 ·哥德巴赫猜想
洛谷 P1581 A+B Problem(升級版)
就是 reg 一個 ack left void 輸出 思路 bad P1581 A+B Problem(升級版) 題目背景 小明這在寫作業,其中有一道A+B Problem ,他想啊想啊想,就是想不出來,於是就找到了會編程的你......
E - The Blocks Problem ( UVA - 101)
num continue blog while break ++ log pos 很多 - 題目大意 先理解給出的四個移動方式: move a onto b:把木塊a、b上的木塊放回各自的原位,再把a放到b上; move a over b:把a上的木塊放回各
題解報告:poj 3320 Jessica's Reading Problem(尺取法)
read line contain text 所有 appear 時間 inpu stream Description Jessica‘s a very lovely girl wooed by lots of boys. Recently she has a probl
【2018ICPC南京網絡賽 A】An Olympian Math Problem(數論題)
for student number 數論 main num title mar ive Alice, a student of grade 6, is thinking about an Olympian Math problem, but she feels so de