Floyd算法的理解

最短路径之Floyd(弗洛伊德)算法,以及显示完整路径 简介: Floyd算法又称为插点法,是一种利用动态规划的思想寻找给定的加权图中多源点之间最短路径的算法,与Dijkstra算法类似。该算法名称以创始人之一、1978年图灵奖获得者、斯坦福大学计算机科学系教授罗伯特·弗洛伊德命名。 我的上一篇文章讲的dijjstra算法,是图中某一个顶点,到其它顶点之间的最短路径.时间复杂度为O(n2),是单源最短路径 而Floyd算法,是图中每一个顶点,到其它顶点之间的最短路径.时间复杂度为O(n3).也被称为多源最短路径问题. 算法思想: 1,逐个顶点试探 2 阅读详情

@转载自:http://developer.51cto.com/art/201403/433874.htm


081028t67l8vd73686e68m.png


暑假,小哼准备去一些城市旅游。有些城市之间有公路,有些城市之间则没有,如下图。为了节省经费以及方便计划旅程,小哼希望在出发之前知道任意两个城市之前的最短路程。


081028xjgvimgz7882qdu7.png



上图中有4个城市8条公路,公路上的数字表示这条公路的长短。请注意这些公路是单向的。我们现在需要求任意两个城市之间的最短路程,也就是求任意两个点之间的最短路径。这个问题这也被称为“多源最短路径”问题。

现在需要一个数据结构来存储图的信息,我们仍然可以用一个4*4的矩阵(二维数组e)来存储。比如1号城市到2号城市的路程为2,则设e[1][2]的值为2。2号城市无法到达4号城市,则设置e[2][4]的值为∞。另外此处约定一个城市自己是到自己的也是0,例如e[1][1]为0,具体如下。

081028o2n5ebn8hdeh9e5l.png

现在回到问题:如何求任意两点之间最短路径呢?通过之前的学习我们知道通过深度或广度优先搜索可以求出两点之间的最短路径。所以进行n2遍深度或广度优先搜索,即对每两个点都进行一次深度或广度优先搜索,便可以求得任意两点之间的最短路径。可是还有没有别的方法呢?

我们来想一想,根据我们以往的经验,如果要让任意两点(例如从顶点a点到顶点b)之间的路程变短,只能引入第三个点(顶点k),并通过这个顶点k中转即a->k->b,才可能缩短原来从顶点a点到顶点b的路程。(此处为理解该算法的重点)那么这个中转的顶点k是1~n中的哪个点呢?甚至有时候不只通过一个点,而是经过两个点或者更多点中转会更短,即a->k1->k2b->或者a->k1->k2…->k->i…->b。比如上图中从4号城市到3号城市(4->3)的路程e[4][3]原本是12。如果只通过1号城市中转(4->1->3),路程将缩短为11(e[4][1]+e[1][3]=5+6=11)。其实1号城市到3号城市也可以通过2号城市中转,使得1号到3号城市的路程缩短为5(e[1][2]+e[2][3]=2+3=5)。所以如果同时经过1号和2号两个城市中转的话,从4号城市到3号城市的路程会进一步缩短为10。通过这个的例子,我们发现每个顶点都有可能使得另外两个顶点之间的路程变短。好,下面我们将这个问题一般化。

当任意两点之间不允许经过第三个点时,这些城市之间最短路程就是初始路程,如下。

081029zdxxq919ttqt8tu8.png

如现在只允许经过1号顶点,求任意两点之间的最短路程,应该如何求呢?只需判断e[i][1]+e[1][j]是否比e[i][j]要小即可。e[i][j]表示的是从i号顶点到j号顶点之间的路程。e[i][1]+e[1][j]表示的是从i号顶点先到1号顶点,再从1号顶点到j号顶点的路程之和。其中i是1~n循环,j也是1~n循环,代码实现如下。

  1. for(i=1;i<=n;i++)   
  2. {   
  3.     for(j=1;j<=n;j++)   
  4.     {   
  5.  if ( e[i][j] > e[i][1]+e[1][j] )   
  6. e[i][j] = e[i][1]+e[1][j];   
  7.     }   
  8. } 

在只允许经过1号顶点的情况下,任意两点之间的最短路程更新为:

081029itl7z7m4l9qqg56d.png

通过上图我们发现:在只通过1号顶点中转的情况下,3号顶点到2号顶点(e[3][2])、4号顶点到2号顶点(e[4][2])以及4号顶点到3号顶点(e[4][3])的路程都变短了。

接下来继续求在只允许经过1和2号两个顶点的情况下任意两点之间的最短路程。如何做呢?我们需要在只允许经过1号顶点时任意两点的最短路程的结果下,再判断如果经过2号顶点是否可以使得i号顶点到j号顶点之间的路程变得更短。即判断e[i][2]+e[2][j]是否比e[i][j]要小,代码实现为如下。

  1. //经过1号顶点   
  2. for(i=1;i<=n;i++)   
  3.     for(j=1;j<=n;j++)   
  4.  if (e[i][j] > e[i][1]+e[1][j])  e[i][j]=e[i][1]+e[1][j];   
  5. //经过2号顶点   
  6. for(i=1;i<=n;i++)   
  7.     for(j=1;j<=n;j++)   
  8.  if (e[i][j] > e[i][2]+e[2][j])  e[i][j]=e[i][2]+e[2][j]; 

在只允许经过1和2号顶点的情况下,任意两点之间的最短路程更新为:

081029e7gjlaaul4zk7z4n.png

通过上图得知,在相比只允许通过1号顶点进行中转的情况下,这里允许通过1和2号顶点进行中转,使得e[1][3]和e[4][3]的路程变得更短了。

同理,继续在只允许经过1、2和3号顶点进行中转的情况下,求任意两点之间的最短路程。任意两点之间的最短路程更新为:

081029pd747o8o87o07o7l.png

最后允许通过所有顶点作为中转,任意两点之间最终的最短路程为:

081030h7tmht7cs2h7qftu.png

整个算法过程虽然说起来很麻烦,但是代码实现却非常简单,核心代码只有五行:

  1. for(k=1;k<=n;k++)   
  2.     for(i=1;i<=n;i++)   
  3.  for(j=1;j<=n;j++)   
  4.      if(e[i][j]>e[i][k]+e[k][j])   
  5.    e[i][j]=e[i][k]+e[k][j]; 

这段代码的基本思想就是:最开始只允许经过1号顶点进行中转,接下来只允许经过1和2号顶点进行中转……允许经过1~n号所有顶点进行中转,求任意两点之间的最短路程。用一句话概括就是:从i号顶点到j号顶点只经过前k号点的最短路程。其实这是一种“动态规划”的思想,关于这个思想我们将在《啊哈!算法2——伟大思维闪耀时》在做详细的讨论。下面给出这个算法的完整代码:

  1. #include <stdio.h>   
  2. int main()   
  3. {   
  4.     int e[10][10],k,i,j,n,m,t1,t2,t3;   
  5.     int inf=99999999; //用inf(infinity的缩写)存储一个我们认为的正无穷值   
  6.     //读入n和m,n表示顶点个数,m表示边的条数   
  7.     scanf("%d %d",&n,&m);   
  8.   
  9.     //初始化   
  10.     for(i=1;i<=n;i++)   
  11.  for(j=1;j<=n;j++)   
  12.      if(i==j) e[i][j]=0;   
  13. else e[i][j]=inf;   
  14.     //读入边   
  15.     for(i=1;i<=m;i++)   
  16.     {   
  17.  scanf("%d %d %d",&t1,&t2,&t3);   
  18.  e[t1][t2]=t3;   
  19.     }   
  20.   
  21.     //Floyd-Warshall算法核心语句   
  22.     for(k=1;k<=n;k++)   
  23.  for(i=1;i<=n;i++)   
  24.      for(j=1;j<=n;j++)   
  25.   if(e[i][j]>e[i][k]+e[k][j] )   
  26.       e[i][j]=e[i][k]+e[k][j];   
  27.   
  28.     //输出最终的结果   
  29.     for(i=1;i<=n;i++)   
  30.     {   
  31.      for(j=1;j<=n;j++)   
  32.  {   
  33.      printf("%10d",e[i][j]);   
  34.  }   
  35.  printf("\n");   
  36.     }   
  37.   
  38.     return 0;   
  39. } 

有一点需要注意的是:如何表示正无穷。我们通常将正无穷定义为99999999,因为这样即使两个正无穷相加,其和仍然不超过int类型的范围(C语言int类型可以存储的最大正整数是2147483647)。在实际应用中最好估计一下最短路径的上限,只需要设置比它大一点既可以。例如有100条边,每条边不超过100的话,只需将正无穷设置为10001即可。如果你认为正无穷和其它值相加得到一个大于正无穷的数是不被允许的话,我们只需在比较的时候加两个判断条件就可以了,请注意下面代码中带有下划线的语句。

  1. //Floyd-Warshall算法核心语句   
  2. for(k=1;k<=n;k++)   
  3.   for(i=1;i<=n;i++)   
  4.       for(j=1;j<=n;j++)   
  5.  if(e[i][k]<inf && e[k][j]<inf && e[i][j]>e[i][k]+e[k][j])   
  6.      e[i][j]=e[i][k]+e[k][j]; 

上面代码的输入数据样式为:

  1. 4 8   
  2. 1 2 2   
  3. 1 3 6   
  4. 1 4 4   
  5. 2 3 3   
  6. 3 1 7   
  7. 3 4 1   
  8. 4 1 5   
  9. 4 3 12 

第一行两个数为n和m,n表示顶点个数,m表示边的条数。

接下来m行,每一行有三个数t1、t2 和t3,表示顶点t1到顶点t2的路程是t3。

得到最终结果如下:

081030is22w3mmnz3r33m3.png

通过这种方法我们可以求出任意两个点之间最短路径。它的时间复杂度是O(N3)。令人很震撼的是它竟然只有五行代码,实现起来非常容易。正是因为它实现起来非常容易,如果时间复杂度要求不高,使用Floyd-Warshall来求指定两点之间的最短路或者指定一个点到其余各个顶点的最短路径也是可行的。

另外需要注意的是:Floyd-Warshall算法不能解决带有“负权回路”(或者叫“负权环”)的图,因为带有“负权回路”的图没有最短路。例如下面这个图就不存在1号顶点到3号顶点的最短路径。因为1->2->3->1->2->3->…->1->2->3这样路径中,每绕一次1->-2>3这样的环,最短路就会减少1,永远找不到最短路。其实如果一个图中带有“负权回路”那么这个图则没有最短路。

081030elthvel6et6k886y.png




ps:要求带有负权边的最短路径,应该看Bellman-Ford算法(该算法用于求单源最短路径)





最短路径问题---Floyd算法详解 前言 Genius only means hard-working all one’s life. Name:Willam Time:2017/3/81、最短路径问题介绍问题解释: 从图中的某个顶点出发到达另外一个顶点的所经过的边的权重和最小的一条路径,称为最短路径解决问题的算法: 迪杰斯特拉算法(Dijkstra算法) 弗洛伊德算法(Floyd算法) SPFA算法 之前已经对Di 阅读详情

相关推荐

基于错误扩散的Floyd-Steinbery抖动算法简单理解

1. 图像处理中的dithering技术 它是一种欺骗你眼睛,使用有限的色彩让你看到比实际图象更多色彩的显示方式。通过在相邻像素间随机的加入不同的颜色来修饰图象,通常这种方式被用于颜色较少的情况下。 2. 错误扩散(Error diffusion) 将当前像素点的误差传递到附近的像素点 3. Floyd–Steinberg dithering 如图:*表示当前的像素点,错

wang_kun888的博客 1万+

Floyd算法求解最短路径

Floyd算法又称为插点法,是一种利用动态规划的思想寻找给定的加权图中多源点之间最短路径的算法,与Dijkstra算法类似。该算法名称以创始人之一、1978年图灵奖获得者、斯坦福大学计算机科学系教授罗伯特·弗洛伊德。核心思路:通过一个图的权值矩阵求出它的每两点间的最短路径矩阵。算法过程:从任意一条单边路径开始。左右两点之间的距离是边的权,如果两点之间没有边相连,则权为无穷大。对于每一对顶点u和v,看是否存在一个顶点w使得从u到w再到v比已知的路径更短,如果更短,则更新它。上述概念来源于百度百科。

冲出仁川,走出马德里,故事还会再继续 2万+

深入理解Floyd算法思路

你真的理解Floyd算法吗 Floyd算法经典代码只有5行(或者也可以写成4行),思路听起来也那么“显然”。 但大部分人对Floyd算法的理解仅仅限于它的实现是三层循环,k在最外层,i和j在内层不分顺序,用路径松弛来更新最短路径。但其实大多数人都没有弄清楚一个问题,为什么外层循环是遍历k,而不是把k放到最内层呢,只是知道放在里边就不对了。当然,也有不少博客解释这个问题,但写的大多有些复杂,下面是我个人的理解。

Talk is cheap,give me the code! 2771

【坐在马桶上看算法】算法6:只有五行的Floyd最短路算法

暑假,小哼准备去一些城市旅游。有些城市之间有公路,有些城市之间则没有,如下图。为了节省经费以及方便计划旅程,小哼希望在出发之前知道任意两个城市之前的最短路程。 上图中有4个城市8条公路,公路上的数字表示这条公路的长短。请注意这些公路是单向的。我们现在需要求任意两个城市之间的最短路程,也就是求任意两个点之间的最短路径。这个问题这也被称为“多源最短路径”...

weixin_30487201的博客 9039

最短路径——Floyd算法

最短路径——Floyd算法

m0_51339444的博客 1万+

《LabVIEW ZYNQ实战指南》第6章>>案例解析:基于USB WiFi模块的ZYNQ无线通信部署与Linux RT开发

本文详细解析了如何为ZYNQ开发板部署USB WiFi模块,实现无线通信。通过LabVIEW Linux RT环境,利用封装好的驱动VI,开发者可轻松配置ZYNQ连接无线网络,摆脱网线束缚,实现程序无线部署与远程调试,为工业物联网应用奠定基础。

app77的博客 755

对floyd算法理解

最基础的floyd写法 for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(e[i][j]>e[i][k]+e[k][j]) e[i][j]=e[i][k]+e[k][j]; 看了一两篇文章,总结一下,首先floyd求的是多源最短路,思想是:一开始用来存图的邻接矩阵对于两个点之间没有其他...

flying_whale1的博客 772

CVAT本地部署保姆级教程:用Docker Compose在Ubuntu上5分钟搞定你的私有数据标注平台

本文提供CVAT本地部署的保姆级教程,详细讲解如何在Ubuntu系统上使用Docker Compose快速搭建私有数据标注平台。从环境准备、Docker配置到CVAT部署全流程,涵盖硬件要求、性能优化及安全加固等关键步骤,帮助开发团队5分钟内完成高效、安全的标注环境搭建。

weixin_42619742的博客 383

深入理解floyd算法

先上floyd算法的代码,本质上是动态规划问题 本质就是DP含有动态规划的思想,满足重叠子问题和最优子结构 dis[k][i][j]=min(dis[k-1][i][j],dis[k-1][i][k]+dis[k-1][k][j]); 我们可以发现他其实是由前k-1的状态来推出第k个点的状态之后你就会发现f[k]只与f[k-1]有关 然后我们可以根据这个性质解决很多问题 for (k = 1; k...

小姑仔的博客 652

Axure原型模板与元件库APP交互设计素材(附资料)

在Axure中,手机模型是展示APP或小程序界面效果的重要工具。通过导入手机模型元件,设计师可以更加直观地模拟真实设备的显示效果,从而更准确地评估设计的可行性和用户体验。Axure官方及第三方资源库中提供了多种品牌和型号的手机模型,如iPhone、Android等,设计师可以根据项目需求选择合适的模型进行使用。Axure作为一款强大的原型设计工具,为APP和小程序的设计与开发提供了丰富的界面组件元件库和交互设计素材。

招风的黑耳优快云 1981

2024年五大革新图像分割模型解析:架构创新与实战应用指南

本文深入解析2024年五大革新图像分割模型,包括SAM2、Mask2Former、DINOv2和Swin Transformer等,探讨其架构创新与实战应用。从多尺度处理、提示交互到自监督学习,这些模型在精度提升、效率优化和交互增强方面取得突破,广泛应用于医疗影像、工业质检和智慧城市等领域。

hadoop5ranger的博客 894

Floyd算法理解及逐步执行分析

一、前言 题主最近在复习《数学分析与建模》课程,在复习图论部分时接触到了Dijkstra算法和Floyd这两个用来求解最短路径的经典算法,在理解Floyd算法时查阅好多其他人的理解,终于大概是弄懂这个算法的工作过程了,把自己的理解写下来作为记录,希望对后来者有所帮助。 二、Floyd算法工作流程分析 和Dijkstra算法不同,Floyd算法用来求解两点间的最短路径问题。它的工作过程如下: (1)构造初始路径举例矩阵,路线矩阵 这里直接引用https://blog.youkuaiyun.com/qq_4251

qq_55600803的博客 441

使用 Mid360 从零开始搭建实物机器人入门级导航系统 —— 基于 Fast_Lio 和 Move_Base

本文详细介绍了如何使用Mid360机器人从零开始搭建一个基于Fast_Lio和Move_Base的入门级导航系统。通过配置 ROS2、集成激光雷达、IMU、Fast_Lio、Move_Base 等模块,我们成功构建了一个能够实现自动导航的机器人系统。在实际开发中,随着需求的变化,你可以不断调整参数、优化路径规划算法、增加新的传感器等,逐步提升机器人的智能与功能。

小蜗牛的珍贵百宝箱 3567

Floyd-Warshall算法的理解

Floyd算法可以求图内任意两点之间的最短路径,三重循环搞定,虽然暴力,但是属于算法当中最难的动态规划的一种,很有必要理解。 花了一晚上和半个下午专门看这个,才看个一知半解,智商被碾压没办法。 我一直怀疑这种办法会不会漏情况,是不是一定正确,脑子里想特殊用例,却把脑子想乱了。 收藏这么几个网址,从数学证明的角度给出强有力的支持,我也是看了这个之后觉得应该是正确的,过段时间再看应该能彻底明白了...

weixin_30599769的博客 122

AI测试:手把手教你用AI生成测试用例并支持导出Excel「喂饭教程」

如果我告诉你,有一种方法,你只需要输入需求内容,AI就能自动帮你设计出结构清晰、覆盖全面的测试用例,并直接生成一份精美的Excel表格,你会不会心动?

blues_C的博客 3885

MATLAB应用实战系列(七十七)-基于长时间序列栅格数据的MK检验

1 MK检验介绍 MK检验是曼-肯德尔法,又称Mann—Kenddall 检验法,是一种气候诊断与预测技术,应用Mann-Kendall检验法可以判断气候序列中是否存在气候突变,如果存在,可确定出突变发生的时间。Mann-Kendall检验法也经常用于气候变化影响下的降水、干旱频次趋势检测。目前常用于长时间序列的栅格数据的显著性检验,在植被覆盖度,NDVI,NPP等方面尤为常见。 该检验功能强大,不需要样本遵从一定的分布,部分数据缺失不会对结果造成影响,不受少数异常值的干扰,适用性强。不但可以检验时

wenyusuran的专栏 6291

对Floyd算法的理解

Floyd(弗洛伊德)

wanglz666的专栏 1959

YOLOv8改进策略【损失函数篇】| 2024 引进Focaler-IoU损失函数 加强边界框回归 (Focaler-DIoU、Focaler-GIoU、Focaler-CIoU)

本文记录的是改进YOLOv8的损失函数,将其替换成。现有研究通过利用边界框之间的几何关系来提高回归性能,但忽略了困难样本和简单样本分布对边界框回归的影响。不同检测任务中困难样本和简单样本的分布不同,对于简单样本占主导的检测任务,关注简单样本的边界框回归有助于提高检测性能;对于困难样本比例较高的检测任务,需要关注困难样本的边界框回归。,提高检测器在不同检测任务中的性能。实现的。

Limiiiing的博客 1223

最短路--关于对floyd算法的理解

今天刚学flody算法,上午学的时候感到很头痛,虽然只有3个for循环,但如果不明白其中的含义的话,还是感觉好难受,所以特意花了一下午和一晚上,对flody算法仔细研究了一下。 先看一下模板代码(此题为无向图): #include <stdio.h> #include <string.h> const int oo = 1<<28;...

weixin_30449453的博客 134

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Floyd算法三重循环理解

最短路Floyd算法三重循环的顺序: for(int k=0; k<=n; ++k) for(int i=0; i<=n; ++i) for(int j=0; j<=n; ++j) map[i][j] = min{ map[i][j], map[i][k]+map[k][j]};Floyd算法本质上是DP,即对于每个(可能的)新增的节点k,来更新(可能的)节点i到j的最短距离。

lxp6164的博客 4376

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

floyd算法的理解

floyd算法适用于APSP(all pairs shortest paths,多源最短路径),是一种动态规划方法 对于稠密图(点的密集度高),执行效率要高于dijkstra和spfa算法,这种方法是用二维数 组来存储点与点之间的距离,所以不适合有大量的点,就像点i到点j之间的距离就存储 在map[i][j]里 接下来讲讲三重循环: for(k=0

星空永恒 976

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Floyd算法的深入理解 尝试魔改核心代码

https://blog.youkuaiyun.com/qq_45492531/article/details/104452588 在我这个博客中,一次训练的机会让我接触到了floyd算法。

待到山花烂漫时 960
上一篇: Struts:关于struts2中namespace和s:form action和form action 路径问题
下一篇: cmd命令
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值