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

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

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

现在回到问题:如何求任意两点之间最短路径呢?通过之前的学习我们知道通过深度或广度优先搜索可以求出两点之间的最短路径。所以进行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。通过这个的例子,我们发现每个顶点都有可能使得另外两个顶点之间的路程变短。好,下面我们将这个问题一般化。

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

如现在只允许经过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循环,代码实现如下。

for(i=1;i<=n;i++){ for(j=1;j<=n;j++) { if ( e[i][j] > e[i][1]+e[1][j] ) e[i][j] = e[i][1]+e[1][j]; }}

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

通过上图我们发现:在只通过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号顶点for(i=1;i<=n;i++) for(j=1;j<=n;j++) if (e[i][j] > e[i][1]+e[1][j]) e[i][j]=e[i][1]+e[1][j];//经过2号顶点for(i=1;i<=n;i++) for(j=1;j<=n;j++) if (e[i][j] > e[i][2]+e[2][j]) e[i][j]=e[i][2]+e[2][j];

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

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

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

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

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

for(k=1;k<=n;k++) for(i=1;i<=n;i++) for(j=1;j<=n;j++) if(e[i][j]>e[i][k]+e[k][j]) e[i][j]=e[i][k]+e[k][j];

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

#include int main(){ int e[10][10],k,i,j,n,m,t1,t2,t3; int inf=99999999; //用inf(infinity的缩写)存储一个我们认为的正无穷值 //读入n和m,n表示顶点个数,m表示边的条数 scanf("%d %d

啊哈算法2伟大思维闪耀时_「坐在马桶上看算法」算法6:只有五行的Floyd最短路算法...相关推荐

  1. 坐在马桶上看算法:只有五行的Floyd最短路算法

    坐在马桶上看算法:只有五行的Floyd最短路算法 此算法由Robert W. Floyd(罗伯特·弗洛伊德)于1962年发表在"Communications of the ACM" ...

  2. 算法6:只有五行的Floyd最短路算法

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

  3. 【啊哈!算法】算法6:只有五行的Floyd最短路算法

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

  4. 【算法】只有五行的Floyd最短路算法

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

  5. 沃舍尔算法_坐在马桶上看算法:只有五行的Floyd最短路算法

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

  6. 坐在马桶上看算法:Dijkstra最短路算法

                                                             [坐在马桶上看算法]算法7:Dijkstra最短路算法 上周我们介绍了神奇的只有五行的 ...

  7. 坐在马桶上看算法:快速排序

    坐在马桶上看算法:快速排序<?xml version="1.0" encoding="UTF-8"?> 坐在马桶上看算法:快速排序    高快省的排 ...

  8. 【坐在马桶上看算法】算法4:队列——解密QQ号

    新 学期开始了,小哈是小哼的新同桌(小哈是个小美女哦~),小哼向小哈询问QQ号,小哈当然不会直接告诉小哼啦,原因嘛你懂的.所以小哈给了小哼一串加密过 的数字,同时小哈也告诉了小哼解密规则.规则是这样的 ...

  9. 【坐在马桶上看算法】算法4:队列――解密QQ号

    新 学期开始了,小哈是小哼的新同桌(小哈是个小美女哦~),小哼向小哈询问QQ号,小哈当然不会直接告诉小哼啦,原因嘛你懂的.所以小哈给了小哼一串加密过 的数字,同时小哈也告诉了小哼解密规则.规则是这样的 ...

  10. 【坐在马桶上看算法】啊哈算法13:零基础彻底弄懂“并查集“

    并查集 题目描述 分析 并查集模板 因为最近在学并查集,在别的博客看到关于并查集的知识点,讲解得很清晰,理解更深,所以搬运到csdn来分享一下好资源. 题目描述 快过年了,犯罪分子们也开始为年终奖&q ...

最新文章

  1. 类和JSON的序列化与反序列化
  2. orion的简单测试
  3. 计算机和网络知识,计算机和网络技术基础知识
  4. select/poll原理(阻塞挂起) 正常(阻塞轮询)
  5. ReadWriteLock读写锁的使用
  6. ASP Blob类型转存为Long Raw类型
  7. 微计算机控制器功能是什么意思,微型计算机中,控制器的基本功能是().
  8. 贯彻落实83号文,超图“互联网+不动产”再升级
  9. Jdt-compiler是什么?有什么作用
  10. 如何判断/获取屏幕的状态(亮屏已解锁,亮屏未解锁,黑屏)
  11. 自己无聊做的一个简单的企业进销存管理系统
  12. 俄罗斯方块游戏系统-c语言版
  13. 小白之路由浅入深之------day05
  14. 使用python实现科学记数法的书面形式输出
  15. Snipaste的使用方法
  16. 微软笔记本服务器怎么重装系统,笔记本重装系统,详细教您笔记本怎么重装win10系统...
  17. 2021安洵杯Misc writeup
  18. 【ES系列】ES的数据结构与DSL语法
  19. 十二大行的金融科技子公司,哪家注册资本最高?
  20. 解决程序缺少richtx32.ocx无法运行问题

热门文章

  1. ghostscript处理PDF/拆分/压缩/合并/转换
  2. 深入浅出通信原理知识点1
  3. Sql Server 当前日期第一天
  4. 在文华财经赢顺云W6和赢顺云手机随身行中如何导入需要的指标
  5. IO操作write()写的文档内不是你设置的buff
  6. Funcode-黄金矿工
  7. java程序的开发流程
  8. eval('{kkk:{}}')出错,eval('{}')与eval('var ss = {kkk:{}}')正常
  9. 还在愁csdn进不去吗,看这里
  10. 关于微信投票微信投票神器及微信刷票软件免费版如何操作微信投票怎么免费刷票