Floyd算法求最短路径
floyd算法用于求图中各个点到其它点的最短路径,无论其中经过多少个中间点。该算法的核心理念是基于动态规划,
不断更新最短距离,遍历所有的点。
知识基础:图的邻接矩阵表示:

如图是一个简单图,从A开始,按照ABCDEFG的顺序来制定一个方阵,该方阵每一行代表一个点到所有点的直达距离,
到它本身的距离是0,如果两点之间没有直接相连(非邻接)的,那么这两点的距离就定位无穷或者-1,例如图中的A点到
其它所有点的距离为 0 7 ∞ 5 ∞ ∞ ∞ 按照ABCDEFG的顺序排列,方阵的每一行从上到下按照ABCDEFG的顺
序排列出各点到各点的距离,这样的方阵就叫做图的邻接矩阵,例如该图的邻接矩阵data为:

由于该图是无向图,所以它的邻接矩阵是先对角线对称的。如果是有向图的话则要根据边的方向来确定点与点间的距离。
编程中,我们一般用二维数组表示邻接矩阵。
算法核心:遍历图中的每一个点,通过该点的入读和出度来计算以该点作为中间点连接另外两点的距离,来与原来的距
离作比较,存最小的值,不断刷新。例如以k为中间点,计算i到j的最短距离,则比较data[i][j] 和data[i][k]+data[k][j]的
大小,如果后者更小,则刷新数组,令data[i][j] = data[i][k]+data[k][j]。由于k值是不断变化的,所以遍历完整个数
组,data[i][j]所存的值就是i到j的最小值。
需要注意的是,由i到j中间可能会经过多个点,所以我们要理解data[i][k]也并非表示i到k的直达距离,一开始data[i][k]
确实是i到k的直达距离,但是随着数组data的不断刷新,点到点的距离不再单是直达距离而是经过0个或多个点的最短距
离。所以data[i][k]中也可能经过多个点。而data[k][j]表示从k到j的直达距离因为后面的距离还没刷新(遍历数组是从上到
下,从左到右)。
记录路径 :定义一个二维数组path来记录各点到各点所经过的中间点,如果两点之间没有中间点的话就以它的起点作为
中间点,这样做的好处是能够通过反推找到完整的路径
代码:
f = float('inf') # float('inf')表示无穷大
# 准备数据
data = [
[0, 7, f, 5, f, f, f],
[7, 0, 8, 9, 7, f, f],
[f, 8, 0, f, 5, f, f],
[5, 9, f, 0, 15, 6, f],
[f, 7, 5, 15, 0, 8, 9],
[f, f, f, 6, 8, 0, 11],
[f, f, f, f, 9, 11, 0],
]
path = [[i] * 7 for i in range(7)]
for k in range(7):
for i in range(7):
for j in range(7):
if data[i][j] > data[i][k] + data[k][j]: # 比较距离的大小
data[i][j] = data[i][k] + data[k][j] # 每次都存最小的值
path[i][j] = k # 记录中间点
# 定义函数找出x到y的具体路径
def show_trace(x,y):
trace = []
def add_trace(x, y):
global mm
if x != y:
add_trace(x, path[x][y])
return trace.append(y)
add_trace(x,y)
trace_str = str(trace)
trace_str = trace_str.replace(',','-->')
print(f"从 {x} 到 {y} 的最短路径为: {trace_str}")
for i in data:
print(i)
show_trace(0,4) # 求A到E的最短路径
show_trace(0,6) # 求A到G的最短路径
#[0, 7, 15, 5, 14, 11, 22]
#[7, 0, 8, 9, 7, 15, 16]
#[15, 8, 0, 17, 5, 13, 14]
#[5, 9, 17, 0, 14, 6, 17]
#[14, 7, 5, 14, 0, 8, 9]
#[11, 15, 13, 6, 8, 0, 11]
#[22, 16, 14, 17, 9, 11, 0]
#从 0 到 4 的最短路径为: [0--> 1--> 4]
#从 0 到 6 的最短路径为: [0--> 3--> 5--> 6]
接下再用2021蓝桥杯pythonA组的题目来深入理解
【问题描述】
小蓝学习了最短路径之后特别高兴,他定义了一个特别的图,希望找到图中的最短路径。
小蓝的图由2021个结点组成,依次编号1至2021
对于两个不同的结点a,b,如果a和b的差的绝对值大于21,则两个结点之间没有边相连;如果a和b的差的绝对值小于等于21,则两个点之间有一条长度为a和b的最小公倍数的无向边相连。
例如:结点1和结点23之间没有边相连;结点3和结点24之间有一条无向边,长度为24;结点15和结点25之间有一条无向边,长度为75.
请计算,结点1和结点2021之间的最短路径长度是多少。
题目分析:该题点与点之间是否直连受到二者差值的约束,线段的距离也是通过计算才能得出,因为是求1到2021的最短距离,所以
只需要1行的矩阵来记录1点到其它所有点的最短距离,同样的,1到2021的通过的中间点也只需要一行矩阵来存储。因此上面代码的
循环在这里可以减少一层。
解题代码:
def fn(x, y):
x1, y1 = x, y
while y1 != 0:
x1, y1 = y1, x1 % y1
return x*y//x1
n = 2021
# 由于一开始不知道1到各点的距离所以全设为无穷大,反正后面会计算求出
data = [float('inf')]*(n+1) # 这里数组向前进一位是为了后面计算最小公倍数更方便
path = [1]*(n+1) #相应地路径数组也要进一位
data[1] = 0 # 1到1的距离是0
for i in range(1, n+1):
for j in range(i+1, i+22):
if j > 2021:
break
if data[j] > fn(i,j) + data[i]:
data[j] = fn(i,j) + data[i]
path[j] = i # 记录中间点
# 显示路径
def show_trace(y):
trace = []
def add_trace(y):
global mm
if 1 != y:
add_trace(path[y])
return trace.append(y)
add_trace(y)
trace_str = str(trace)
trace_str = trace_str.replace(',','-->')
print(f"从 1 到 {y} 的最短路径为: {trace_str}")
print(data[n])
# 10266837
show_trace(25)# 路径太长了这里就不展示了
Floyd算法求最短路径的更多相关文章
- _DataStructure_C_Impl:Floyd算法求有向网N的各顶点v和w之间的最短路径
#include<stdio.h> #include<stdlib.h> #include<string.h> typedef char VertexType[4] ...
- Dijkstra算法求最短路径(java)(转)
原文链接:Dijkstra算法求最短路径(java) 任务描述:在一个无向图中,获取起始节点到所有其他节点的最短路径描述 Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到 ...
- C++迪杰斯特拉算法求最短路径
一:算法历史 迪杰斯特拉算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题.迪杰斯特拉算法主要特点是以 ...
- js迪杰斯特拉算法求最短路径
1.后台生成矩阵 名词解释和下图参考:https://blog.csdn.net/csdnxcn/article/details/80057574 double[,] arr = new double ...
- 【POJ - 2139】Six Degrees of Cowvin Bacon (Floyd算法求最短路)
Six Degrees of Cowvin Bacon Descriptions 数学课上,WNJXYK忽然发现人缘也是可以被量化的,我们用一个人到其他所有人的平均距离来量化计算. 在这里定义人与人的 ...
- Floyd 算法求多源最短路径
Floyd算法: Floyd算法用来找出每对顶点之间的最短距离,它对图的要求是,既可以是无向图也可以是有向图,边权可以为负,但是不能存在负环(可根据最小环的正负来判定). 基本算法: Floyd算法基 ...
- [Python] 弗洛伊德(Floyd)算法求图的直径并记录路径
相关概念 对于一个图G=(V, E),求图中两点u, v间最短路径长度,称为图的最短路径问题.最短路径中最长的称为图的直径. 其中,求图中确定的某两点的最短路径算法,称为单源最短路径算法.求图中任意两 ...
- 《算法导论》读书笔记之图论算法—Dijkstra 算法求最短路径
自从打ACM以来也算是用Dijkstra算法来求最短路径了好久,现在就写一篇博客来介绍一下这个算法吧 :) Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到其他所有节点的 ...
- _DataStructure_C_Impl:Dijkstra算法求最短路径
// _DataStructure_C_Impl:Dijkstra #include<stdio.h> #include<stdlib.h> #include<strin ...
- 通俗易懂理解——dijkstra算法求最短路径
迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径.它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止 ###基本思想 通过Dij ...
随机推荐
- oracle排查慢sql
查询最慢的SQL select * from (select sa.SQL_TEXT, sa.SQL_FULLTEXT, sa.EXECUTIONS "执行次数", round(s ...
- 小程序使用webview嵌套H5两边如何传参.
需求:项目里面需要进行人脸核身.需要调起小程序的人脸核身功能.需要h5跳转到小程序页面.验证完后回退 1.h5页面先引入一个js文件 2.当用微信小程序的web-view内嵌H5页面的时候,H5页面的 ...
- 前端BootStrap框架和django创建项目和app
1.JS 正则 test - 判断字符串是否符合规定的正则 rep = /\d+/; rep.test("asdfoiklfasdf89asdfasdf") # true rep ...
- uniapp 弹窗输入
借鉴链接:https://blog.csdn.net/qq_40894259/article/details/110200721 <template> <view class=&qu ...
- 遍历List时删除元素导致List抛出java.util.ConcurrentModificationException异常
1 public static void main(String[] args) { 2 List<String> list = new ArrayList<String>() ...
- JS字符串拼接的方法及性能比较
一.+和+=str += "one" + "two";这段代码在运行过程中,会经历四个步骤:1.在内存中创建一个临时字符串2.将连接后的字符串"one ...
- Error: (1061, "Duplicate key name 'makerphoto_user_info_email_380c93a0_uniq'")
django.db.utils.OperationalError: (1061, "Duplicate key name 'makerphoto_user_info_email_380c93 ...
- OpenMP fortran 学习
参考自TAMU的PPThttps://people.math.umass.edu/~johnston/PHI_WG_2014/OpenMPSlides_tamu_sc.pdf 什么是OpenMP 在C ...
- 微信小程序笔记_02
在微信小程序中使用Echarts组件 github源码地址:https://github.com/ecomfe/echarts-for-weixin gitcode源码地址:https://gitco ...
- SpringBoot导读
SpringBoot 一.导读 1.开发工具及技术栈 JDK:jdk1.8.0_191 开发工具:IntelliJIDEA 2020.3.2 SpringBoot: 简化Spring的开发 需要一定的 ...