旅行商问题(TSP):给定一组城市和每对城市之间的距离,问题是找到最短的路线,该路线恰好访问每个城市一次并返回起点。
注意哈密顿循环和 TSP 之间的区别。 Hamiltoninan 循环问题是寻找是否存在一次访问每个城市恰好一次的旅行。这里我们知道哈密顿环存在(因为图是完整的)并且实际上存在许多这样的环,问题是找到一个最小权重的哈密顿环。
例如,考虑右侧图中所示的图形。图中的 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)?
为了使用动态规划计算成本(i),我们需要在子问题方面有一些递归关系。让我们定义一个术语C(S, i) 是访问集合 S 中每个顶点一次的最小成本路径的成本,从 1 开始到 i 结束。
我们从大小为 2 的所有子集开始,并为所有子集计算 C(S, i),其中 S 是子集,然后我们为所有大小为 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-1 的 n-2 个子集,这样所有子集中都没有第 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
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。