使用Dijkstras找到“k”最短路径

时间:2014-06-15 23:05:01

标签: c# algorithm dijkstra path-finding

我已经可以使用Dijkstra算法找到两个顶点之间的最短路径:wiki Dijkstra's

BUT。我的一些边缘被用作"检查点",因为你必须通过至少一个检查点才能使路线可用。

有时,算法会找到一条不包含这些边缘检查点的路径。在那种情况下,我想找到第二个。最短路线 - 如果该路线也不包含检查点,则找到第3个路线。最短的路线,等等。

如何让我开始的任何想法?

编辑:

是否可以通过第一条路线上的所有前辈,然后从前任到目的地运行Dijkstras(并排除前一个前一个goto顶点的原始选择)。通过这种方式,我可以找到所有可能的路线,然后将它们相互比较?

实施例

A =来源 Z =目的地

最短路径:A - > B - > C - > D - > ž

第二。最短路径:A - > B - > C - > D - > " Vertex成本最低,不是Z" (如果在当前的尝试中没有找到可用的路径,请通过所有D的未访问的邻居循环)

如果是第二名。最短路径也不包含检查点,尝试第3个最短

第三。最短路径:A - > B - > C - >顶点成本最低,不是D

或者这种解决方案无法以任何方式实现吗?

编辑2:

Picture 可能很难看到,但紫色的1x3像素是顶点。黄色的道路是边缘,粉红色的3x3像素也是如此。粉红色的也是所谓的检查站。所以我必须找到最短的路线并至少经过一个检查站。

5 个答案:

答案 0 :(得分:2)

有几种方法可以尝试使这项工作。

让我们称S为起始节点,D为目标节点,I为中间节点。

[单个中间节点] 一个简单但次优的解决方案是使用从S到I的Dijkstra,然后将Dijkstra的结果从I添加到D.

[多个中间节点] 正如Niklas B.所指出的那样,一种可行的方法是" 从S和D构建最短路径树。对于每个中间节点A,检查d(S,A)+ d(T,A)。最小的解决方案。运行时间是Dijkstra的两倍,例如具有二进制堆的O((n + m)log n)"。

答案 1 :(得分:1)

我的建议是 - 添加更多尺寸来存储chekpoints传递的内容。

因此,状态(x1,x2)将替换为:(x1,x2,c1...c_n)其中c1..cn是每个检查点的布尔标志。

(x1,x2)->(y1,y2)将被替换为:

  • (x1,x2, c1..cn)->(y1,y2, c1..cn)用于非检查点状态
  • (x1,x2, c1..cn)->(y1,y2, c1..c(x-1), true ,c(x+1)..cn)用于检查点状态cx

适用于任何c1..cn

搜索算法本身是相同的,但状态数将乘以2^n

修改 此外,如果需要匹配至少一个(不是很少的不同)检查点,则向量c1..cn可以被一个标志替换,该标志将描述至少一个检查点通过。

答案 2 :(得分:0)

根据图表更改的频率,您可以尝试使用Floyd Warshall算法。它将帮助您构建一个矩阵,显示任何节点对之间的最短路径。完成后,您可以使用Saverio Terracciano的答案迭代检查点,找出哪个检查点是最佳检查点。

答案 3 :(得分:0)

对于每个节点,您拥有n个最低成本,而不是最低成本,其中n是访问所需的检查点数。假设你说你需要N / M和订单以及N无关紧要。

然后,当您传播费用时,您会跟踪检查点并更新相应的n个插槽以获取所需信息。您可能希望将n限制为最小值,因为如果您需要2个检查点并且通过3,则仍然有2个,但额外值没有值。

答案 4 :(得分:0)

您还可以将此转换为TSP问题以获得最佳路线:

  • 对起始节点S和中间节点I
  • 使用正常权重
  • 使用从S到终端节点E的无限权重(我们只想删除/忽略连接起点和终点的往返)
  • 使用0权重连接终点E和起点S

现在为每个检查点:

  • 将检查点添加为基本行程的中间点
  • 使用TSP计算游览长度,使用Dijkstra计算节点之间的距离并记住通过此检查点的长度

这些旅行中最短的是最佳旅行,并且只通过一个检查点。