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 ...
随机推荐
- Docker 基础常用命令
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows操作系统的机器上,也可以实现虚拟化.Docker是内核 ...
- GIS空间分析和建模复习重点1
1.对空间分析的理解(对概念的理解) 空间分析是为了解答地理空间问题而进行的数据分析与挖掘,是GIS的核心.研究对象为空间目标(具有空间特性(位置,分布,形态,空间关系(距离,方位,拓扑)),属性特性 ...
- shell - scriptreplay timing.log output.session
script -t 2> timing.log -a output.session cmd cmd cmd exit scriptreplay timing.log output.session ...
- 浅谈组件二封-vue
目录 组件二封不是换一种写法 组件二封应当具备哪些条件 我认为的二封应当有哪些作用 二封的好处 先来一个列表页demo来看看效果(Vue2) 本文仅仅针对vue系列做探讨, 项目倾向于大量增删改查的后 ...
- -behaviour()的使用,他具体有什么作用
Eralng 编程中的OTP OTP里面创建进程时 常用有四大behaviour • supervisor • gen_server • gen_fsm • gen_event 在erlang的编译器 ...
- EBS关于LPN的API【OM】
PROCEDURE create_lpn(x_return_status OUT NOCOPY VARCHAR2, p_box_item_id IN NUMBER, p_box_number IN V ...
- webrtc windows编译记录
//cmd set path=D:\zzh\depot_tools;%path% set DEPOT_TOOLS_WIN_TOOLCHAIN 0 set vs2022_install=C:\Progr ...
- #maxlength vs #size form api reference
#maxlength Used by: password, textfield Description: The maximum amount of characters to accept as i ...
- composer 操作
composer list 显示所有命令 composer show 显示所有包信息 composer install 在 composer.json 配置中添加依赖库之后运行此命令安装 compos ...
- Vue项目的打包方式(生成dist文件)
一.相关配置情况一(使用的工具是 vue-cil) 如果是用 vue-cli 创建的项目,则项目目录中没有 config 文件夹,所以我们需要自建一个配置文件:在根目录 src 下创建文件 vue.c ...