思想:Dijkstra是求单源最短路径,Floyd算法是用于求多源最短路径,算出来的是所有的节点到其余各节点之间的最短距离。
Dijkstra算法
先遍历一下还没有在最短路中的点,选出一个距离 已经在最短路集合中的点 距离最近的点(遍历与 最短路包含的点 相连的节点),并把它加入到最短路中,并且更新所有点的最短路,直到所有的点都加入到最短路中。
图解参考:https://www.cnblogs.com/Glacier-elk/p/9438077.html
操作步骤
(1) 初始时,S只包含起点s;U包含除s外的其他顶点,且U中顶点的距离为"起点s到该顶点的距离"[例如,U中顶点v的距离为(s,v)的长度,然后s和v不相邻,则v的距离为∞]。
(2) 从U中选出"距离最短的顶点k",并将顶点k加入到S中;同时,从U中移除顶点k。
(3) 更新U中各个顶点到起点s的距离。之所以更新U中顶点的距离,是由于上一步中确定了k是求出最短路径的顶点,从而可以利用k来更新其它顶点的距离;例如,(s,v)的距离可能大于(s,k)+(k,v)的距离。
(4) 重复步骤(2)和(3),直到遍历完所有顶点。
例子
#leetcode1368困难
class Solution:
def minCost(self, grid: List[List[int]]) -> int:
#0302 30min
'''Dijkstra 算法适合用来求出无负权边图中的单源最短路径。其中「无负权边」表示图中所有边的权值必须为非负数,「单源最短路径」表示 Dijkstra 算法可以求出从某一个节点到其余所有节点的最短路径。'''
m, n = len(grid), len(grid[0])
BIG = int(1e9)
dist = [0] + [BIG] * (m * n - 1) #无穷,到每个点距离
seen = set()#访问过的节点
q = [(0, 0, 0)] #第一个节点加入
while len(q) > 0:
cur_dis, x, y = heapq.heappop(q) #获取到这个点的所有最短路径更新,
if (x, y) in seen:##已经获得最短节点,不再遍历
continue
seen.add((x, y)) #加入
cur_pos = x * n + y #当前位置
for i, (nx, ny) in enumerate([(x, y + 1), (x, y - 1), (x + 1, y), (x - 1, y)]):
new_pos = nx * n + ny
new_dis = dist[cur_pos] + (1 if grid[x][y] != i + 1 else 0) #难点:不相等不能到nx,xy
if 0 <= nx < m and 0 <= ny < n and new_dis < dist[new_pos]:
dist[new_pos] = new_dis #更新最短路径
heapq.heappush(q, (new_dis, nx, ny))
return dist[m * n - 1]
Floyd
第一、先找出最短的距离
第二、然后在考虑如何找出对应的行进路线。
如何找出最短路径呢,这里还是用到动态规划的知识,
所以可以令k=1,2,3,...,n(n是城市的数目),在检查d(ij)与d(ik)+d(kj)的值
若有d(ij)>d(ik)+d(kj):d(ij)=d(ik)+d(kj),重复这一过程,最后当查完所有的k时,d(ij)里面存放的就是i到j之间的最短距离了。
1. 用i,j两个变量分别指向二元组里的两个元素,比如{0,1}这个二元组,i指向0;j指向1
2. 判断 (A[ i ][ 0 ]+A[ 0 ][ j ] ) < A[ i ][ j ] (即判断 i -> j,i点到j点的距离是否小于从0点中转的距离),如果false,则判断下一组二元数组。
3. 如果表达式为真,更新A[ i ] [ j ]的值为A[ i ] [ 0 ] + A[ 0 ] [ j ],Path[ i ] [ j ]的值为点0(即设置i到j要经过0点中转)
来源:CSDN
作者:serenysdfg
链接:https://blog.csdn.net/serenysdfg/article/details/104616427