对于具有n个顶点和m条边且边的权值非负的简单图(无重边和环),K短路,是指的起点s到终点t的最短路径中第k个最小的。K短路分为有限制的K短路和无限制的K短路,有限制的K短路是指求得的路径中不含有回路(路径上任何一个节点的出现次数不大于1次),无限制的K短路则对求得的路径中没有要求,这篇博客先讨论前者,后讨论后者。
本篇博客中使用的无向图实例如下图所示

如上图所示,求解节点A至节点C的K短路。本篇博客主要使用经典的A*算法。
1 A*算法简介。
通用图搜索路径常用的启发式搜索
其中f(x)称为评估函数,g(n)为从初始节点S到节点n的实际代价,h(n)是从节点n到目标节点T的最 优路径的评估代价,被称为启发式函数,它体现了问题的启发式信息。
由此引出A*算法:
定义评估函数:
在上式中,g*(n)是从起始节点S到节点n的最短路径的代价,h*(n)是从节点n到目标节点T的最短路径的代价。shi因为有可能最短路径还没找到,所以一般情况下有g(n)>=g*(n)
同时h(n)<=h*(n),就是说h(n)是h*(n)的下界,这个限制确保A*算法可以找到最优解。对于一个问题,启发式函数h(n)的设计通常有多种,一般有如下关系
(1)h(n)=0,A*算法退化为dijkstra算法,可以找到最优解
(2)h(n)<=h*(n),A*算法可以找到最优解,不过收敛速度较慢,h(n)越小,收敛速度越慢
(3)h(n)=h*(n),A*算法可以找到最优解,收敛速度很快,扩展的节点全是最短路径上的点
(4)h(n)>h*(n),A*算法不一定能找到最优解,但收敛速度很快。
2 求解过程
用A*算法求解K短路问题,可以概括为如下步骤。首先,定义评估函数
,其中g(n)是从起始节点S到达节点的n的实际代价,定义为从起始节点S到达节点n的路径上所经过边的权值之和,h(n)为从节点n到达目标节点的最短路径的代价,记为dis[],实现的方法是构建反图,以终点T为起点对全图进行一次dijkstra算法得到(在这里,h(n)=h*(n)),以上图为例,从节点C到各个节点的dis值如下:
dis[C]=0,dis[B]=2,dis[A]=3,dis[D]=4
定义如下结构:queue[]为优先级队列,count[]为节点出现的次数。这样f(n)代表从起点节点到目标节点的最短路径的费用。刚开始,queue[]只有起始节点,算法步骤如下
(1)从优先级队列选取队头元素,如果fx值相同则选取gx较小的
(2)用队头元素去更新其子女节点的f(n)值,并将子女节点入队
(3)当取出的队头元素是终点时,计算其出现次数,若是K次,算法结束,否则将其子女入队。
对上图,求解节点A到节点C的K短路,具体的求解过程如下:
(b)queue[]={A}
g(1)=0,h(1)=dis[A]=3;
f(1)=g(1)+h(1)=0+3=3;
(b)节点A出队,其子女节点B、C、D入队,
用f(1)更新其子女节点B、C、D的f值
g(2)=g(1)+w(A-B)=0+1=1(w(A-B)代表边A-B的权值)
h(2)=dis[B]=2;
f(2)=g(2)+h(2)=1+2=3;对应节点为B
g(3)=g(1)+w(A-C)=0+4=4;
h(3)=dis[C]=0;
f(3)=g(3)+h(3)=4+0=4;对应节点为C;
g(4)=g(1)+w(A-D)=0+1=1;
h(4)=dis[D]=4;
f(4)=g(4)+h(4)=1+4=5;对应节点为D
queue[]={2,3,4}
(c)节点2出队,

本文介绍了如何使用A*算法解决无向图中起点到终点的无环K短路问题。首先,通过dijkstra算法求得反图中各节点的最短距离dis[],然后利用A*算法寻找最短路径。在A*算法中,通过优先级队列选取节点,并更新其子女节点,直到找到K条不同的最短路径。最后,通过在节点入队前检查是否存在环路,确保得到的路径无环。文中给出了具体例子及C++实现代码。
最低0.47元/天 解锁文章
987

被折叠的 条评论
为什么被折叠?



