我会尝试编写一个 A* 算法来解决这个问题。当你扩展一个节点时,你会为每个输出顶点得到两个孩子;一个你喝咖啡的地方,一个你不喝的地方。如果您使用 Dijkstra 的运行对您的算法进行预处理(因此您已经预先计算了最短路径),那么您可以使用 Dijkstra 的最短路径 + 喝咖啡的最短时间(如果咖啡已经喝完,则为 + 0)告知 A* 搜索的启发式.
当您不仅到达目标节点而且还喝了咖啡时,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* 出发有意义的地方
我还不确定我们是否需要通过我们喝咖啡的节点来区分“喝咖啡”状态,但我倾向于不需要。