我试图在离散能量景观中找到两个最大值之间的最短路径,其中最短路径是在总路径的过程中降低最小高度的路径。可能最大的能量路径是更正确的术语,但换句话说,即使路径在景观周围长距离行进但不会进入山谷,它也会被认为是好的。
我最初的想法是创建一个景观图,其中权重是邻居之间景观高度的差异,分别为负上升和下降的正面。我刚刚意识到这不会给出我需要的结果,实际上局部最大值之间的所有路径都会有完全相同的成本。
然后我意识到如果这个图上节点之间的距离取决于当前位置和路径的历史,那么我可以得到我需要的结果。例如如果这条小路从一个山谷上下来,那么我就不会给另一个山谷分配额外的费用(只要路径不超过它以前没有达到的低点)。那么是否存在图搜索算法,其中距离可以随着路径的探索而动态变化?
还是有其他建议可以解决这个问题吗?
答案 0 :(得分:7)
这被称为瓶颈最短路径问题。它实际上比最短路径问题更容易,并且可以在无向图上的线性时间内求解。请参阅示例here。
答案 1 :(得分:2)
我建议使用一种算法来构建一个辅助树(T),其中每个节点都包含一个顶点列表。每个子树将包含一组顶点,这些顶点通过山谷与图的其余部分分开。要找到任意两个节点之间的距离,只需要在树中找到它们最低的共同祖先。
初始化:
O(V)
,时间:O(V log V)
)r
MakeTree(G, r)
:
G
中的最低顶点,将其从图表中移除并添加到根r
中的列表中(每个顶点的时间成本:O(1 + E/V)
)G'
的每个关联组件G
:
n
,将该节点作为根MakeTree(G', n)
现在你有了一个具有这样一个属性的树,如果你想从顶点A
到B
,你的最大能量路径将通过存储在最低点的最高顶点A
和B
的共同祖先。为了找到距离,只需找到最低共同祖先并获取存储在那里的最高顶点C
并计算max(abs(h(A) - h(C)), abs(h(B) - h(C)))
。
下面是一个示例图和相应的树(为简洁起见,顶点标签是它们的高度)。例如,如果你想从22变为14,你必须通过10(树中最低共同祖先的最高顶点,距离= 22 - 10)。如果你想从22到20,你必须通过13(距离= 22 - 13)。
答案 2 :(得分:1)
可能以下工作:
创建景观图,权重为dist + abs(height_a - height_b)。
abs功能使得上升或下降变得昂贵,正如您已经注意到的那样,单独的高度差是不够的,因为无论您在哪条路线上任何两点,它都是恒定的去。
dist是普通距离(或者在所有情况下甚至是常数1)并且可能被省略,但是如果你想获得短路径,这应该有利于短期以及相同的成本。
当然没有经过测试。 : - )
答案 3 :(得分:1)
鉴于端点处于最大值,您的问题与此相同:
对于图中的x,设h(x)为起点下方的距离。 (根据问题的陈述,所有点都低于起点)。
找到最小化的路径:max(路径中x的h(x))。
你可以使用Dijkstra最短路径的变体来解决这个问题。我已经从维基百科复制并修改了算法的描述(只有步骤3中的距离计算发生了变化)。
为每个节点分配一个距离值。对于我们的初始节点,将其设置为零,对于所有其他节点,将其设置为无穷大。
将所有节点标记为未访问。将初始节点设置为当前节点。
对于当前节点,考虑其所有未访问的邻居并计算它们的暂定距离(从初始节点开始)。例如,如果当前节点(A)的距离为6,并且连接到另一个节点(B)且h(B)= 7,则到B到A的距离将是max(6,7)= 7。如果这样距离小于先前记录的距离(开头的无穷大,初始节点为零),覆盖距离。
当我们考虑当前节点的所有邻居时,将其标记为已访问。将不再检查受访节点;现在记录的距离是最终的,最小的。 如果已访问所有节点,请完成。否则,将具有最小距离(从初始节点)的未访问节点设置为下一个“当前节点”,并从步骤3继续。
答案 4 :(得分:1)
所以你根本不关心总路径长度,对吧?只是你在路径上遇到的最小值?
如果是这种情况,那么你不应该使用传统意义上的“距离”作为Dijkstra的费用。您的优先级队列应返回具有最高能量值的节点 - 这样,如果存在更好的路径,则保证永远不会通过较低的值。
我认为这与@Paul Hankin在答案中的建议不同。这可能会在图中打开很多节点;我认为您可以按如下方式进行优化:
使用[欧几里德或曼哈顿]到目标的距离作为比较函数中的决胜局。这样,如果两个节点具有相同的能量,您将尝试更快地到达目标的节点。
将节点添加到优先级队列时,不要将其实际能量用于“成本”,而是使用其能量的最小值和迄今为止遇到的最小能量。由于你只关心全球最低成本,一旦你被迫采取低能耗节点,所有高于“成本”的东西都是相同的。这使搜索的行为类似于目标附近的正常A *搜索。
在局部最大值的较低处开始搜索(我不是肯定的,但我认为会更快)。
在#1中使用距离作为决胜局不会影响最小能量,但它应该让事情运行得更快(有点像A *搜索)。
编辑:这是一种完全不同(但可能更慢)的思考方式。
首先,选择一个阈值能量。执行标准Dijkstra / A *搜索,但拒绝任何能量低于阈值的节点。如果您没有路径,请选择更大的阈值并重试。 “安全”的初始猜测是从开始到目标的简单路径(例如,向左然后向上)的最小E.
现在增加阈值,重做Dijkstra / A *。继续这样做,直到找不到路径。无法再找到路径之前的最后一条路径是沿路径具有最大最小能量的最短路径。
您也可以将一次搜索的路径成本重新用作下一次搜索的改进A *启发式。由于增加阈值只会增加路径的长度,因此它是admissible heuristic。
希望有所帮助。如果有什么不清楚,请告诉我。
答案 5 :(得分:0)
两种可能性。
a)例如http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm处的版本有一条线可以通过点u来确定到点v的距离可能有所改善:
alt:= dist [u] + dist_between(u,v)
14如果alt< dist [v]://放松(u,v,a)
15 dist [v]:= alt
16 previous [v]:= u
您似乎想要一个版本 alt:= K - min(高度[u],高度[v])。这与添加版本的原因大致相同:在任何时候从Q中删除的顶点集都具有从源到的任何路径正确计算出的最小成本。每次从Q中移除顶点时,因为要移除距离最小的顶点,所以使用Q中的其他顶点不可能有任何短切。
b)如果从源头开始有路线,请采取任何方法进行计算。使用仅包含高度> = H的点的图表,看看是否有解决方案。尝试各种H,直到找到一个正常工作。您可以提前对所有高度进行排序,然后在此阵列上使用二进制切换。