使用循环排列来减少旅行商的复杂性

时间:2014-03-23 04:19:34

标签: java algorithm circular-permutations

我正在尝试一系列不同的算法来寻找Traveling Salesman Problem的近似最优解,其中一种方法就是蛮力方法 - 检查每条之间的可能路径n个城市,只需返回最好的城市。这是一个O(n!)算法,因此很自然地需要很长时间来执行大量城市。

我想提高我的暴力实施的效率,我注意到的一件事是你不必检查城市的每个单个排列。例如,如果您有城市1,2,3和4,则路径(1-2-3-4)与路径(2-3-4-1)的长度相同。路径(3-4-1-2)和(4-1-2-3)也是如此。通过利用这一事实,我们应该能够将蛮力算法的复杂性从O(n!)降低到O((n-1)!),甚至O((n-1)!/ 2)如果我们意识到所有路径都可以反转,而不会影响它们的长度。

基本上,我正在寻找一种能够从一组不同的整数生成circular permutations的算法。如果算法将“镜像”排列视为等效(例如1-2-3和3-2-1是相同的,因此只需要其中一个),这也是很好的。有谁知道这样做的方法? Java实现会很精彩,但我会采取任何措施!

2 个答案:

答案 0 :(得分:4)

如果您始终使用相同的节点(例如' 1'),则不应遇到此问题。然后你也可以轻松添加镜像检查,因为它只是从节点0运行到N-1 N-2,直到你再次为零。

例如,1,2,3,4具有以下排列:

1234 1243 1324 1342 1423 1432 2134 2143 2314 2341 2413 2431
3124 3142 3214 3241 3412 3421 4123 4132 4213 4231 4312 4321 

现在,如果我们强制将1作为第一个节点,那么您最终会得到这些独特的解决方案:

1234 1243 1324 1342 1423 1432

接下来我们可以消除镜像'解决方案:

normal => reverse => rotated by 1
1234 => 4321 => 1432
1243 => 3421 => 1342
1324 => 4231 => 1423

您只需要查看:

1234 1243 1324

<强>更新

生成此序列的最简单方法是枚举1 ... N-1的所有可能性,其中1在2之前(强制方向)并附加N.

例如,对于N = 4,我们首先生成所有排列1 ... N-1:

123 132 213 231 312 321 

现在我们在2之前过滤1:

123 132 312

追加N(4):

1234 1324 3124

这可能更容易,也更有效。这也证明了暴力TSP所需的上限是:(N - 1)! / 2

答案 1 :(得分:0)