📜  旅行推销员问题|设置1(天真和动态编程)

📅  最后修改于: 2021-04-27 17:36:22             🧑  作者: Mango

旅行推销员问题(TSP):给定一组城市并确定每对城市之间的距离,问题在于找到一条最短的路线,该路线可以精确地访问每个城市一次并返回起点。
注意汉密尔顿周期和TSP之间的差异。汉密尔顿循环问题是要找出是否存在一次游览每个城市一次的旅行。在这里,我们知道存在汉密尔顿巡回赛(因为该图是完整的),并且实际上存在许多此类巡回赛,问题在于找到最小权重的汉密尔顿循环。

欧拉1

例如,考虑右侧图所示的图形。图中的TSP巡视是1-2-4-3-1。游览费用为10 + 25 + 30 + 15,即80。

该问题是著名的NP难题。没有多项式时间已知的解决方案来解决此问题。

以下是旅行商问题的不同解决方案。

天真的解决方案:
1)以城市1为起点和终点。
2)生成所有(n-1)个!城市的排列。
3)计算每个排列的成本,并跟踪最小成本排列。
4)以最小的成本返回排列。

时间复杂度:Θ(n!)

动态编程:
令给定的顶点集为{1,2,3,4,…. n}。让我们考虑1作为输出的起点和终点。对于其他每个顶点i(非1),我们找到以1为起点,i为终点且所有顶点仅出现一次的最小成本路径。假设这条路径的成本为cost(i),相应的Cycle的成本为cost(i)+ dist(i,1),其中dist(i,1)是从i到1的距离。最后,我们返回所有[cost(i)+ dist(i,1)]值中的最小值。到目前为止,这看起来很简单。现在的问题是如何获得成本(i)?
为了使用动态规划计算cost(i),我们需要在子问题方面具有一定的递归关系。让我们定义项C(S,i)为从1开始到i精确地访问集合S中每个顶点的最小成本路径的成本
我们从大小为2的所有子集开始,并为其中S是子集的所有子集计算C(S,i),然后为大小为3的所有子集S计算C(S,i),依此类推。请注意,每个子集中必须存在1。

If size of S is 2, then S must be {1, i},
 C(S, i) = dist(1, i) 
Else if size of S is greater than 2.
 C(S, i) = min { C(S-{i}, j) + dis(j, i)} where j belongs to S, j != i and j != 1.

对于一组大小为n的集合,我们考虑n-2个子集,每个子集的大小为n-1,以使所有子集中没有第n个子集。
使用上述递归关系,我们可以编写基于动态编程的解决方案。最多有O(n * 2 n )个子问题,每个子问题都需要线性时间来求解。因此,总运行时间为O(n 2 * 2 n )。时间复杂度远小于O(n!),但仍然是指数级的。所需空间也是指数的。因此,即使顶点数量稍多,此方法也不可行。

我们将很快讨论旅行商问题的近似算法。

下一篇:旅行商问题套装2

参考:
http://www.lsi.upc.edu/~mjserna/docencia/algofib/P07/dynprog.pdf
http://www.cs.berkeley.edu/~vazirani/algorithms/chap6.pdf