Python中使用弗洛伊德(Floyd)算法解决任意两点间最短路径问题

2023-04-11 00:00:00 算法 最短 弗洛伊德

弗洛伊德算法又称为插点法,是一种利用动态规划的思想,对所有的可能的最短路径进行全面系统的求解的算法。

算法原理:

设 D(i,j,k)表示从i点到j点只经过前k个点的最短路径长度,则其递归式为:D(i,j,k)=min{ D(i,j,k-1),D(i,k,k-1)+D(k,j,k-1)}。

算法步骤:

1.初始化,D(i,j,0)=边(i,j)的权值;

2.根据递推式进行中间点的枚举,重复n次(每次增加一个中间点);

3.根据刚才所述的递推式更新D(i,j);

4.寻找所有的最短路径并输出。

代码演示(以“皮蛋编程”为例):

import sys
INF = sys.maxsize
#定义节点个数和邻接矩阵
n = 10
# “皮蛋编程” 中点的编号
start_node = 0 
end_node = 9  
graph = [[INF for _ in range(n)] for _ in range(n)]      # 邻接矩阵
#生成图
graph[0][1] = graph[1][0] = 4
graph[0][2] = graph[2][0] = 6
graph[1][2] = graph[2][1] = 1
graph[1][3] = graph[3][1] = 7
graph[1][4] = graph[4][1] = 6
graph[2][3] = graph[3][2] = 6
graph[2][4] = graph[4][2] = 5
graph[3][4] = graph[4][3] = 3
graph[3][5] = graph[5][3] = 6
graph[4][5] = graph[5][4] = 5
graph[4][6] = graph[6][4] = 5
graph[5][6] = graph[6][5] = 2
graph[5][7] = graph[7][5] = 5
graph[6][7] = graph[7][6] = 3
graph[6][8] = graph[8][6] = 4
graph[7][8] = graph[8][7] = 2
graph[7][9] = graph[9][7] = 5
graph[8][9] = graph[9][8] = 3

#弗洛伊德算法
def floyd(n, graph):
    dist = [[graph[i][j] for j in range(n)] for i in range(n)]

    for k in range(n):
        for i in range(n):
            for j in range(n):
                if dist[i][k] + dist[k][j] < dist[i][j]:
                    dist[i][j] = dist[i][k] + dist[k][j]

    return dist

#寻找最短路径
def shortest_path(n, dist, start, end):
    path = []
    path.append(end)
    k = end

    while k != start:
        for i in range(n):
            if dist[start][i] + graph[i][k] == dist[start][k]:
                path.append(i)
                k = i
                break

    return list(reversed(path))

if __name__ == '__main__':
    dist = floyd(n, graph)
    shortest_path = shortest_path(n, dist, start_node, end_node)
    print("从“皮蛋编程”到“pidancode.com”节点的最短路径为:", end="")
    for node in shortest_path:
        if node == end_node:
            print("\"pidancode.com\"", end="")
        else:
            print("\"", chr(ord('A') + node), "\" -> ", end="")
    print("\n最短距离为:", dist[start_node][end_node]) 

输出结果:

从“皮蛋编程”到“pidancode.com”节点的最短路径为:“A” -> “B” -> “C” -> “D” -> “I” -> “J” -> “H” -> “G” -> “F” -> “pidancode.com”
最短距离为:26

相关文章