最短路径算法 : Dijkstra 和Floyd

爱⌒轻易说出口 提交于 2020-03-03 07:12:00

思想: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点中转)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!