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算法求最短路径的更多相关文章

  1. _DataStructure_C_Impl:Floyd算法求有向网N的各顶点v和w之间的最短路径

    #include<stdio.h> #include<stdlib.h> #include<string.h> typedef char VertexType[4] ...

  2. Dijkstra算法求最短路径(java)(转)

    原文链接:Dijkstra算法求最短路径(java) 任务描述:在一个无向图中,获取起始节点到所有其他节点的最短路径描述 Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到 ...

  3. C++迪杰斯特拉算法求最短路径

    一:算法历史 迪杰斯特拉算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题.迪杰斯特拉算法主要特点是以 ...

  4. js迪杰斯特拉算法求最短路径

    1.后台生成矩阵 名词解释和下图参考:https://blog.csdn.net/csdnxcn/article/details/80057574 double[,] arr = new double ...

  5. 【POJ - 2139】Six Degrees of Cowvin Bacon (Floyd算法求最短路)

    Six Degrees of Cowvin Bacon Descriptions 数学课上,WNJXYK忽然发现人缘也是可以被量化的,我们用一个人到其他所有人的平均距离来量化计算. 在这里定义人与人的 ...

  6. Floyd 算法求多源最短路径

    Floyd算法: Floyd算法用来找出每对顶点之间的最短距离,它对图的要求是,既可以是无向图也可以是有向图,边权可以为负,但是不能存在负环(可根据最小环的正负来判定). 基本算法: Floyd算法基 ...

  7. [Python] 弗洛伊德(Floyd)算法求图的直径并记录路径

    相关概念 对于一个图G=(V, E),求图中两点u, v间最短路径长度,称为图的最短路径问题.最短路径中最长的称为图的直径. 其中,求图中确定的某两点的最短路径算法,称为单源最短路径算法.求图中任意两 ...

  8. 《算法导论》读书笔记之图论算法—Dijkstra 算法求最短路径

    自从打ACM以来也算是用Dijkstra算法来求最短路径了好久,现在就写一篇博客来介绍一下这个算法吧 :) Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到其他所有节点的 ...

  9. _DataStructure_C_Impl:Dijkstra算法求最短路径

    // _DataStructure_C_Impl:Dijkstra #include<stdio.h> #include<stdlib.h> #include<strin ...

  10. 通俗易懂理解——dijkstra算法求最短路径

    迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径.它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止 ###基本思想 通过Dij ...

随机推荐

  1. 05 Java 数组

    Java 数组 一.什么是数组 数组是相同类型数据的有序集合 数组描述的是相同类型的若干个数据,按照一定的顺序排列组合而成 其中每一个数据称为数组元素,每个数组元素可以通过下标来访问它们 二.数组的声 ...

  2. kubernetes弃用dockershim

    转载自:https://www.51cto.com/article/710688.html 前段时间,kubernetes推出了1.24版本,曾经轰动一时的docker弃用也正式实装了,这意味着1.2 ...

  3. 安装netbense时提示在此计算机中找不到Java SE开发工具包(JDK)

    在提示信息中显示的需要JDK8或更高版本,这边需要提醒大家不要把jdk8和jdk1.8弄混 首先大家打开控制面板找到程序并点击进去 点击程序和功能 在电脑上查看是否有java8或更高版本的内容如果没有 ...

  4. 自定义select组件

    (声明:当前记录篇参考于该人员 https://www.jb51.net/article/166679.htm ) 一.创建组件 1.新建文件夹:select 2.新建Component: selec ...

  5. 四、配置docker MySQL 修改编码,支持 utf8mb4

    docker 获取 mysql 5.7 版本的镜像. 将docker 里面的 3306 端口映射出来,否则虚拟机外,可能无法访问, 创建 docker 镜像 docker run -itd -p 33 ...

  6. Linux 常用监控指标总结

    1. Linux运维基础采集项 做运维,不怕出问题,怕的是出了问题,抓不到现场,两眼摸黑.所以,依靠强大的监控系统,收集尽可能多的指标,意义重大.但哪些指标才是有意义的呢,本着从实践中来的思想,各位工 ...

  7. tomcat代理,监控及性能优化

    第1章 tomcat简介Tomcat是Apache软件基金会(Apache Software Foundation)的Jakarta项目中的一个核心项目,由Apache,Sun和其他一些公司及个人共同 ...

  8. Codeforces Round #781 (Div. 2) - D. GCD Guess

    GCD + 位运算 [Problem - 1665D - Codeforces](https://codeforces.com/problemset/problem/1627/D) 题意 交互题,有一 ...

  9. c++ 继承访问控制初步

    访问控制方式这里有篇很好的文章,其实内容也是总结c++primer上的内容 现在就按照这篇的文章举例进行学习. 思路 不同继承方式的影响主要体现在: 1.派生类成员对基类成员的访问控制. 2.派生类对 ...

  10. windows下git bash不显示中文问题解决

    问题: 在git bash下输入git log,查看log记录的时候中文显示不出来 解决方案: 网上查了很多解决方法,逐个尝试 1.尝试 git config --global core.quotep ...