最短路径
Dijkstra
思路
基本步骤:
- 选定一个点,满足:
- 未被选过
- 距离最短
- 对这个点的所有邻接点尝试松弛(如下图,从a到c权值为5,而从a到b到c权值为3,我们用后者代替前者成为最短路,此之为成功的松弛)
从a开始,依次寻找下一个节点,使得从a到当前节点的路径最短,直到找到结尾
遍历时,我们依次寻找a到当前节点的最短路径以及最近节点
当我们得到了最短权值,我们可以反推回a从而获取最短路径
用矩阵表示如下
代码
邻接矩阵
1 |
|
最小堆优化
上述朴素算法的问题:
- 寻找最小点时,通过遍历n个点来获得最小点
- 对该点邻接点进行松弛时,我们也是通过遍历去寻找邻接点
对于以上问题,我们可以选用小根堆与邻接表直接获取,可以实现代码的优化
1 |
|
Floyd
思路
Floyd与Dijkstra都是看节点间的值,但是前者看的是每两点间最短距离
Dis数组,记录两点距离:
这里矩阵中每个位置表示两点间的距离,而D上的下标表示从何处中转得到的距离(-1表示不进行中转)
如此时
Path数组,记录经过点(最短路径)
Path数组记录了两点间经过的中转点是哪个点,若为直达则记录终点,如
通过path数组推出最短路径:
如寻找
代码
(邻接矩阵)
1 |
|
A*
解决问题:给定原点与目标点,最少代价路径是什么
特点:与dijkstra不同,A*算法考虑从原点到当前点的距离+当前点到目标点距离的估计距离,最后排大小
如该方格,起点为G,终点为U
从G到U预估走4步,G到G走0步,故参与排序为0+4,放入小根堆,并将原点到当前点距离放入distance表中
G 4取出,G到L,N,H,F为1,放入distance,并分别算出到U的预估距离,相加放入小根堆
在取出堆顶并重复上述操作
dij可以看作A*每次预估距离都为0,是一个特例
预估函数
预估函数是一种吸引力,合适的预估函数(越接近真实距离)会大大提升速度
要求:预估距离小于等于到终点的真实距离
预估距离经常选择:曼哈顿距离、欧氏距离、对角线距离等
如:若允许走斜线,曼哈顿距离就不能保证正确性了,此时可以取行与行、列与列间差值最大值
板子
1 |
|