A* 算法

先来想想这么一个题目:

在方格图中,有 \(M\) 个障碍,不能通过这些障碍。给定起点坐标和终点坐标,求出最短路。

1. 贪心最优搜索和 Dijkstra 算法

  1. 贪心最优搜索

贪心最优搜索的流程是:从起点出发,在它的邻居结点上选择离终点最近的点。但是这样往往不能取得最优解。其思想为只看终点,不管起点

  1. Dijkstra 算法

Dijkstra 的流程是:从起点出发,在它的邻居结点上选择里起点最近的点。但是这样搜索是盲目的。其思想为只看起点,不管终点

2. A* 算法的原理

A* 算法结合了这两个算法,即既看起点,也看终点。它比 Dijkstra 快,因为它不像 Dijkstra 一样盲目。它比贪心最优搜索更准确,因为它可以找到最短路。

那么如何结合呢?

设起点为 \(s\),终点为 \(t\)。当走到点 \(i\) 的时候,可以把 \(s \rightarrow t\) 的路径分为 \(s \rightarrow i \rightarrow t\)

  1. \(s \rightarrow i\) 的距离,可以在扩散搜索的时候记录。

  2. \(i \rightarrow t\) 的距离,用贪心最优搜索来预测下一个结点。

以上思路可以用估价函数具体操作。即:

\(f(i)=g(i)+h(i)\)

其中 \(f(i)\) 是对 \(i\) 的评估,\(g(i)\) 是记录的距离,\(h(i)\) 是到终点的曼哈顿距离。

每次根据最小的 \(f(i)\) 选择下一个点,可以使用优先队列选择最小的点。这样当 \(i=t\) 时,\(f(i)\) 即为最短路。

3 种算法的对比

这张图可以直观地解释出来。

其中黑色格子是障碍,数字是估价,有数字的格子是该算法搜索到的格子。

在这个图中,A* 算法会先访问所有估价为 \(10\) 的格子,接着访问 \(12,14\),然后到达终点。

h 函数的设计

应遵循以下三条规则:

  1. \(g\)\(h\) 应采用同样的计算方法。例如 \(g\) 是曼哈顿距离,\(h\) 也应是曼哈顿距离。

  2. 根据应用情况正确选择 \(h\)。如题目要就计算曼哈顿距离,就不能选择欧氏距离。

  3. \(h\) 应该优于实际存在的所有路径。这是最重要的一条规则。如果不这样,程序可能会选择另一条非最优的路径,会造成错误。

A* 算法例题

例题 POJ-2449/洛谷-P2901

这道题可以用 A* 算法解决。

我们每搜到一个一个点时,就将它与它的距离加入优先队列,并用它去扩展更多的点。优先队列中弹出的节点顺序就是距离的顺序。当终点 \(t\)\(K\) 次从优先队列弹出,就是第 \(K\) 短路径。

接下来考虑估价函数。\(g(i)\) 表示 \(s \rightarrow i\) 的距离,可以在扩展的时候计算。\(h(i)\) 表示 \(i \rightarrow t\) 的距离,可以建一个反图,然后用 Dijkstra 求所有点到终点的最短距离。、

时间复杂度为 \(\mathcal{O}(NK \log N)\)

代码

posted @ 2024-02-08 21:06  lrx139  阅读(20)  评论(0编辑  收藏  举报