这个问题是前面提到的问题的延伸:
Least cost path in a sorted array
给定排序数组A
,例如{4,9,10,11,19}
。从i->j
搬迁的费用为
abs(A[j] - A[i]) + cost_incurred_till_i
。从给定元素开始,例如10
。找到最低成本路径而不访问相同的元素两次。
对于给定的数组:
10->9->4->11->19 cost: 1+(1+5)+(1+5+7)+(1+5+7+8) = 41
10->4->9->11->19 cost: 5+(5+5)+(5+5+2)+(5+5+2+8) = 47
10->9->11->4->19 cost: 1+(1+2)+(1+2+7)+(1+2+7+15) = 39
10->11->9->4->19 cost: 1+(1+2)+(1+2+5)+(1+2+5+15) = 35 --one of optimal paths
10->11->19->9->4 cost: 1+(1+8)+(1+8+10)+(1+8+10+5) = 53
10->11->19->4->9 cost: 1+(1+8)+(1+8+15)+(1+8+15+5) = 63
...
我试图用最近邻法来解决这个问题。
i = start
While (array is not empty)
ldiff = A[i] - A[i-1]
rdiff = A[i+1] - A[i]
(ldiff < rdiff) ? sum += ldiff : sum += rdiff
remove A[i]
在这种情况下,最近邻居适用于我们没有相等加权路径的情况。我意识到这是TSP问题。什么是解决这个问题的最佳方法?我应该使用像Christofides或其他算法的TSP启发式算法吗?
答案 0 :(得分:0)
你很近,你可以稍微修改最近的邻居。当两个邻居相等时,检查该邻居的过去元素,然后进入与相反的方向(更靠近)(以避免回溯太多)。如果这些元素距离相同,那就继续向前看,直到它们没有。如果你在看到差异之前达到了界限,那就去吧。
你的例子很好看:
我们唯一的分支点是决定是否在9
的第一步中访问11
或10
。通过两个方向浏览它们会显示4
和19
。 4
更接近10
,因此请远离11
。
显然,对于没有很多顺序均匀间隔元素的数组,这会更快。如果它们的 none 均匀分布,那么它将与您的相同,以n
步进行。
最糟糕的情况是,您必须在每一步都看到一直两端,这将访问每个元素。由于我们为每个n
元素运行一次,因此它出现在 O(n ^ 2)。一个例子是一个带有所有均匀间隔元素的数组,从死点开始搜索。
答案 1 :(得分:0)
有一个O(n 2 )动态编程解决方案。我不知道它是否是最佳的。
下一个选择始终是未访问节点中的直接邻居,因此访问节点形成连续范围。逻辑子问题是在给定受访节点范围的情况下找到部分解决方案。子问题的最佳解决方案仅取决于访问范围和最后访问的节点(必须是其中一个端点)。
可以使用标识访问范围的两个索引对子问题进行编码,该顺序指示最后访问的节点。子问题(a,b)的解决方案是部分解决方案,假设从 min(a,b)到 max(a,b)的节点已经被访问过, a 是最后访问过的节点。它可以递归地定义为
更好insert(a, solve(a - dir, b))
insert(a, solve(b + dir, a))
如果 b &gt; = a ,则 dir 为1,否则为-1。
有两个基本案例。子问题(0,n-1)具有解决方案{A[0]}
,子问题(n-1,0)具有解决方案{A[n-1]}
。这些对应于最终选择,它是第一个节点或最后一个节点。
完整的问题对应于子问题(s,s),其中 s 是起始元素的索引。