如何计算旅行推销员比特币之旅的最佳路径?

时间:2009-05-17 16:54:10

标签: algorithm graph dynamic-programming

已更新

在更多阅读之后,可以给出具有以下递归关系的解决方案:

(a) When i = 1 and j = 2, l(i; j) = dist(pi; pj )
(b) When i < j - 1; l(i; j) = l(i; j - 1) + dist(pj-1; pj)
(c) When i = j - 1 and j > 2, min 1<=k<i (l(k; i) + dist(pk; pj ))

现在开始有意义,除了C部分。我如何确定最小值k?我想这意味着你可以迭代所有可能的k值并只存储(l(k,i)+ dist(pk,pj)的最小结果?


是的,这绝对是我在学校学习的一个问题。我们正在研究旅行商问题的比特之旅。

无论如何,说我有5个顶点{0,1,2,3,4}。我知道我的第一步是按照增加x坐标的顺序对它们进行排序。从那里开始,我对动态编程如何完成这一点感到困惑。

我正在阅读我应该扫描已排序节点的列表,并为两个部分(初始路径和返回路径)保持最佳路径。我对如何计算这些最佳路径感到困惑。例如,我如何知道是否应该在初始路径或返回路径中包含给定节点,因为它不能同时包含在两者中(端点除外)。回想一下斐波纳契的动态编程,你基本上从基础案例入手,继续前进。我想我要问的是如何开始使用比特尼旅行推销员的问题?

对于像Fibonacci数字这样的东西,接近的动态编程非常清楚。但是,我不知道我是不是只是在密集或什么,但我很困惑试图解决这个问题。

感谢您的期待!

注意:我不是在寻找完整的解决方案,但至少有一些很好的提示可以让我开始。例如,如果这是Fibonacci问题,可以说明如何计算前几个数字。请告诉我如何改进这个问题。

2 个答案:

答案 0 :(得分:14)

澄清您的算法。

l(i,j)递归函数应计算访问所有小于i -> 1 -> j的节点的bitonic tour i的最小距离。因此,初始问题的解决方案将是l(n,n)

重要说明:

  1. 我们可以假设节点按其x坐标排序并相应标记(p1.x < p2.x < p3.x ... < pn.x)。它们没有订购,我们可以在O(nlogn)时间对它们进行排序。

  2. l(i,j) = l(j,i)。原因是在lhs中,我们有一个i ->...-> 1 -> ... -> j巡回赛是最佳的。然而,向后穿过这条路线会给我们相同的距离,并且不会破坏比特的属性。

  3. 现在简单的案例(注意变化!):

    (a) When i = 1 and j = 2, l(i; j) = dist(pi; pj ) = dist(1,2)
    

    我们在这里进行了以下巡视:1->1->...->2。通常,这相当于路径1->...->2的长度。由于点是按.x坐标排序的,因此12之间没有任何关系,因此连接它们的直线将是最佳点。 (在2之前选择要访问的任意数量的其他点将导致更长的路径!)

    (b) When i < j - 1; l(i; j) = l(i; j - 1) + dist(pj-1; pj)
    

    在这种情况下,我们必须到j-1,因为argmin k (d(k,j) ) = j-1。 (可以在最短路径上到达j的节点是j-1)。因此,这相当于巡视:i -> ... -> 1 -> .... -> j-1 -> j,相当于l(i,j-1) + dist(pj-1,pj)

    Anf最后有趣的部分来了:

    (c) When i = j - 1 or i = j, min 1<=k<i (l(k; i) + dist(pk; pj ))
    

    我们知道我们必须从i1,但是对于向后扫描没有任何线索!这里的关键思想是我们必须在我们的后向路径上j之前考虑节点。它可能是1j-1的任何节点!我们假设这个节点是k。 现在我们进行一次巡演:i -> ... -> 1 -> .... -> k -> j,对吧?这次旅行的费用是l(i,k) + dist(pk,pj)

    希望你明白了。

    实现。

    您需要一个二维数组BT[1..n][1..n]。设{1}为行索引,i为列索引。我们该如何填写这张表?

    在第一行,我们知道jBT[1][1] = 0,因此我们只有BT[1][2] = d(1,2)个索引属于i,j类别。

    在剩下的行中,我们从对角线填充元素直到结束。

    以下是C ++代码示例(未经测试):

    (b)

答案 1 :(得分:3)

好的,动态编程解决方案中的关键概念是:

  • 你预先计算出较小的问题
  • 您有一条规则可以让您将较小的问题结合起来找到更大问题的解决方案
  • 你有一个已知的问题属性,让你证明解决方案在一定程度上是最优的。 (在这种情况下,最短。)

bitonic游览的基本属性是坐标系中的垂直线与闭合多边形的一侧最多相交两次。那么,究竟是两点的比特之旅是什么?显然,任何两点形成(退化)比特奇之旅。三点有两个bitonic游览(“顺时针”和“逆时针”)。

现在,你怎么能预先计算各种较小的比特奇旅行并将它们组合起来,直到你得到所有的分数并且还有一个比特尼之旅?


好的,你正在跟踪你的更新。但现在,在动态编程解决方案中,您所做的工作是自下而上:预计算和memoize(而非“记忆”)最佳子问题。