我有n
个顶点和m
无向加权边(权重代表分钟)。每个顶点包含在该顶点上喝咖啡所需的分钟数。
我想确定从顶点v
到顶点w
所需的最短时间(分钟),但需要额外的限制,我必须在其中一个顶点上喝咖啡在从v
到w
)的路上。
示例:
(顶点中的数字是喝咖啡所需的分钟数,边缘上的重量代表了此边缘所需的分钟数)
从v
到w
并在途中喝咖啡,输出最短的必要时间(输出应为30)。
我当前的方法是找到Dijkstra的最短路径(总结该路径上所有边的权重),然后在该路径上添加咖啡时间最短的顶点值我的结果是为了获得从v
到w
所需的总时间。
我的方法不起作用,这是一个我的方法失败的例子(我的方法的结果是12分钟,实际结果应该是6分钟):
如何确定从顶点v
到w
的最短时间,以及我需要在路径上喝咖啡的约束?
答案 0 :(得分:7)
解决此问题的标准方法是:
制作2张图表副本 - need_coffee
版本和had_coffee version
。
将每个need_coffee
节点与相应的had_coffee
节点相连,边缘成本等于该节点喝咖啡的成本。
使用Dijkstra算法查找从V_need_coffee
到W_had_coffee
的最短路径
答案 1 :(得分:1)
我会尝试编写一个A *算法来解决这个问题。展开节点时,每个传出顶点都会有两个子节点;一个你喝咖啡的地方,另一个你不喝咖啡的地方。如果你使用Dijkstra(你已经有预先计算的最短路径)对算法进行预处理,那么你可以通过Dijkstra的最短路径+最短时间通知A *搜索的启发式算法。喝咖啡(如果咖啡已经喝完,可以喝+0)。
当您不仅到达目的地节点,而且还喝了咖啡时,A *搜索终止(您已达到目标)。
搜索第二种情况的示例:
Want: A --> C
A(10) -- 1 -- B(10) -- 1 -- C(10)
\ /
\ /
2 -------- D(2) ------- 2
Expand A
A*(cost so far: 10, heuristic: 2) total est cost: 12
B (cost so far: 1, heuristic: 1 + 2) total est cost: 3
B*(cost so far: 11, heuristic: 1) total est cost: 12
D (cost so far: 2, heuristic: 2 + 2) total est cost: 6
D*(cost so far: 14, heuristic: 2) total est cost: 16
Expand B
A*(cost so far: 12, heuristic: 2) total est cost: 14
B*(cost so far: 11, heuristic: 1) total est cost: 12
C(cost so far: 2, heuristic: 2) total est cost: 4
C*(cost so far: 12, heuristic: 0) total est cost: 12
Expand C
B*(cost so far: 13, heuristic: 1) total est cost: 14
C*(cost so far: 12, heuristic: 0) total est cost: 12
Expand D
A* (cost so far: 14, heuristic: 2) total est cost: 16
D* (cost so far: 4, heuristic: 2) total est cost: 6
C (cost so far: 4, heuristic: 0 + 2) total est cost: 6
C* (cost so far: 6, heuristic: 0) total est cost: 6
Expand C*
goal reached. total cost: 6
Key:
* = Coffee from parent was drunk
所以你可以看到这个算法将会做的是首先尝试沿着Dijkstra的最短路径(从不喝咖啡)。然后当它到达终点时,它将看到物理目标状态,但仍需要仍然喝咖啡。当它扩展这个物理目标状态以喝咖啡时,它会看到到达的成本不是最理想的,所以它继续从另一个分支搜索并继续。
请注意,在上文中,A和A *是不同的节点,因此在某种程度上您可以重新访问父节点(但仅限于咖啡饮用状态不同)。 这是为了解决这样一个图:
Want A-->B
A(20) -- 1 -- B(20)
\
2
\
C(1)
从A-> C-> C * - > A * - > B *
开始是有意义的我还不确定我们是否需要区分“喝咖啡”#34;我们在哪个节点喝咖啡,但我倾向于否。
答案 2 :(得分:1)
一种方法如下:
这样做会导致算法与Dijkstra的算法具有相同的时间复杂度(如果你在步骤1和2中使用Dijkstra的算法)