地图路由

题目

目标。优化 Dijkstra 算法,使其可以处理给定图的数千条最短路径查询。 一旦你读取图(并
可选地预处理),你的程序应该在亚线性时间内解决最短路径问题。一种方法是预先计算出
所有顶点对的最短路径;然而,你无法承受存储所有这些信息所需的二次空间。你的目标是
减少每次最短路径计算所涉及的工作量,而不会占用过多的空间。 建议你选择下面的一些
潜在想法来实现,或者你可以开发和实现自己的想法。

想法 1. Dijkstra 算法的朴素实现检查图中的所有 V 个顶点。 减少检查的顶点数量的一种策
略是一旦发现目的地的最短路径就停止搜索。 通过这种方法,可以使每个最短路径查询的
运行时间与 E’ log V’成比例,其中 E’和 V’是 Dijkstra 算法检查的边和顶点数。

想法 2. 你可以利用问题的欧式几何来进一步减少搜索时间,这在算法书的第 4.4 节描述过。
对于一般图,Dijkstra 通过将 d[w]更新为 d[v] + 从 v 到 w 的距离来松弛边 v-w。 对于地图,
则将 d[w]更新为 d[v] + 从 v 到 w 的距离 + 从 w 到 d 的欧式距离 − 从 v 到 d 的欧式距离。
这种方法称之为 A*算法。这种启发式方法会有性能上的影响,但不会影响正确性。

想法 3. 使用更快的优先队列。 在提供的优先队列中有一些优化空间。 你也可以考虑使用
Sedgewick 程序中的多路堆(Multiway heaps, Section 2.4)。

求解

我们将分别完成题述的三个想法,将过程可视化,并比较运行时间。

本文都以起点:6000,终点:1000为例。

测试数据

最终代码:

想法一

即给定目的地,遇到目的地就停止(early exit)。

输出如下:

running time :358.943s
1000 to 6000
distance: 6637.540854006546

可视化如下:

运行过程中,算法从出发点一圈一圈往外探索,直至遇到目的地。

想法二

即给dijkstra加一个启发函数,优先级不止考虑当前点到出发点的距离,也将考虑到目的地的距离。

输出如下:

running time :111.123s
1000 to 6000
distance: 6637.540854006546

可视化如下:

可见,A*算法比dijkstra算法更具目的性,直指目的地探索,运行时间不到dijkstra算法的三分之一。

想法三

即更换优先队列,这里我们将索引优先队列更改为索引2-路优先队列。

输出如下:

running time :107.39s
1000 to 6000
distance: 6637.540854006546

可视化如下:

可以发现,使用多路优先队列运行时间又减少了一些。


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!