前言 在图论中,在寻路最短路径中除了dijkstra算法以外,还有floyd算法也是非常经典,然而两种算法还是有区别的,floyd主要计算多源最短路径。
在单源正权值最短路径,我们会用dijkstra算法来求最短路径,并且算法的思想很简单—贪心算法:每次确定最短路径的一个点然后维护(更新)这个点周围点的距离加入预选队列,等待下一次的抛出确定。虽然思想很简单,实现起来是非常复杂的,我们需要邻接矩阵(表)储存长度,需要优先队列(或者每次都比较)维护一个预选点的集合。还要用一个boolean数组标记是否已经确定、还要……
总之,dijkstra算法的思想上是很容易接受的,但是实现上其实是非常麻烦的。但是单源最短路径解算暂时还没有有效的办法,复杂度也为o(n2)。
而在n点图中想求多源最短路径,如果从dijkstra算法的角度上,需要将dijkstra执行n次才能获得所有点之间的最短路径,不过执行n次dijkstra算法即可,复杂度为o(n3)。但是这样感觉很臃肿,代码量巨大,占用很多空间内存。有没有啥方法能够稍微变变口味呢?
答案是有的,今天就带大家一起了解一下牛逼轰轰的floyed算法。
算法介绍 什么是floyed算法?
floyd算法又称为插点法,是一种利用动态规划的思想寻找给定的加权图中多源点之间最短路径的算法,与dijkstra算法类似。该算法名称以创始人之一、1978年图灵奖获得者、斯坦福大学计算机科学系教授罗伯特·弗洛伊德命名。
简单的来说,算法的主要思想是动态规划(dp),而求最短路径需要不断松弛(熟悉spfa算法的可能熟悉松弛)。
而算法的具体思想为:
1 .邻接矩阵(二维数组)dist储存路径,数组中的值开始表示点点之间初始直接路径,最终是点点之间的最小路径,有两点需要注意的,第一是如果没有直接相连的两点那么默认为一个很大的值(不要因为计算溢出成负数),第二是自己和自己的距离要为0。
2 .从第1个到第n个点依次加入松弛计算,每个点加入进行试探枚举是否有路径长度被更改(自己能否更新路径)。顺序加入(k枚举)松弛的点时候,需要遍历图中每一个点对(i,j双重循环),判断每一个点对距离是否因为加入的点而发生最小距离变化,如果发生改变(变小),那么两点(i,j)距离就更改。
2 .重复上述直到最后插点试探完成。
其中第2步的状态转移方程为:
dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]) 其中dp[a][b]的意思可以理解为点a到点b的最短路径,所以dp[i][k]的意思可以理解为i到k的最短路径dp[k][j]的意思为k到j的最短路径.
咱们图解一个案例,初始情况每个点只知道和自己直接相连的点的距离,而其他间接相连的点还不知道距离,比如a-b=2,a-c=3但是b-c在不经过计算的情况是不知道长度的。
加入第一个节点a进行更新计算,大家可以发现,由于a的加入,使得本来不连通的b,c点对和b,d点对变得联通,并且加入a后距离为当前最小,同时你可以发现加入a其中也使得c-d多一条联通路径(6+3),但是c-d联通的话距离为9远远大于本来的(c,d)联通路径2,所以这条不进行更新。
咱们继续加入第二个节点b,这个点执行和前面a相同操作进行。对一些点进行更新。因为和b相连的点比较多,可以产生很多新的路径,这里给大家列举一下并做一个说明,这里新路径我统一用1表示,原来长度用0表示。
af1=ab+bf=6+2=8 < af0(∞) 进行更新
ae1=ab+be=2+4=6 < ae0(∞) 进行更新
ce1=cb+be=5+5=9 < ce0(∞) 进行更新
cf1=cb+bf=5+6=11
ef1=eb+bf=4+6=10ac0(3) 不更新
ad1=ab+bd=2+8=10>ad0(6) 不更新
……
更多路径这里就不一一列举了。
后序加入c、d、e、f都是进行相同的操作,最终全部加完没有路径可以更新就结束停止。实际上这个时候图中的连线就比较多了。这些连线都是代表当前的最短路径。 这也和我们的需求贴合,我们最终要的是所有节点的最短路径。每个节点最终都应该有5条指向不同节点的边! 矩阵对应边值就是点点之间最短路径。
至于算法的模拟两部核心已经告诉大家了,大家可以自行模拟剩下的。
程序实现 而对于程序而言,这个插入的过程相当简单。核心代码只有四行! 这个写法适合有向图和无向图,无向图的算法优化后面会说。 代码如下
public class floyd { static int max = 66666;// 别intege.max 两个相加越界为负 public static void main(string[] args) { int dist[][] = { { 0, 2, 3, 6, max, max }, { 2, 0, max, max,4, 6 }, { 3, max, 0, 2, max, max }, { 6, max, 2, 0, 1, 3 }, { max, 4, max, 1, 0, max }, { max, 6, max, 3, max, 0 } };// 地图 // 6个 for (int k = 0; k < 6; k++)// 加入第k个节点进行计算 { for (int i = 0; i < 6; i++)// 每加入一个点都要枚举图看看有没有可以被更新的 { for (int j = 0; j < 6; j++) { dist[i][j] = math.min(dist[i][j], dist[i][k] + dist[k][j]); } } } // 输出 for (int i = 0; i < 6; i++) { system.out.print(节点+(i+1)+ 的最短路径); for (int j = 0; j [城市 1, 城市 2] 城市 1 -> [城市 0, 城市 2, 城市 3] 城市 2 -> [城市 0, 城市 1, 城市 3] 城市 3 -> [城市 1, 城市 2] 城市 0 和 3 在阈值距离 4 以内都有 2 个邻居城市,但是我们必须返回城市 3,因为它的编号最大。
示例2:
输入:n = 5, edges = [[0,1,2],[0,4,8],[1,2,3],[1,4,2],[2,3,1],[3,4,1]], distancethreshold = 2 输出:0 解释:城市分布图如上。 每个城市阈值距离 distancethreshold = 2 内的邻居城市分别是: 城市 0 -> [城市 1] 城市 1 -> [城市 0, 城市 4] 城市 2 -> [城市 3, 城市 4] 城市 3 -> [城市 2, 城市 4] 城市 4 -> [城市 1, 城市 2, 城市 3] 城市 0 在阈值距离 2 以内只有 1 个邻居城市。
提示:
2 <= n <= 100 1 <= edges.length <= n * (n - 1) / 2 edges[i].length == 3 0 <= fromi < toi < n 1 <= weighti, distancethreshold <= 10^4 所有 (fromi, toi) 都是不同的。
思路分析:
拿到一道题,首先就是要理解题意,而这道题的意思借助案例也是非常能够理解,其实就是判断在distancethreshold范围内找到能够到达的最少点的编号,如果多个取最大即可。正常求到达最多情景比较多这里求的是最少的,但是思路都是一样的。
这道题如果使用搜索,那复杂度就太高了啊,很明显要使用多源最短路径floyd算法,具体思路为;
1 .先使用floyd算法求出点点之间的最短距离,时间复杂度o(n3)
2 . 统计每个点与其他点距离在distancethreshold之内的点数量,统计的同时看看是不是小于等于已知最少个数的,如果是,那么保存更新。
3 .返回最终的结果。
实现代码:
class solution { public int findthecity(int n, int[][] edges, int distancethreshold) { int dist[][]=new int[n][n]; for(int i=0;i 有的,这个是个无向图,也就是加入点的时候枚举其实会有一个重复的操作过程(例如枚举ac和ca是效果一致的),所以我们在floyd算法的实现过程中过滤掉重复的操作,具体代码为:
class solution { public int findthecity(int n, int[][] edges, int distancethreshold) { int dist[][]=new int[n][n];//存储距离 for(int i=0;i floyd像什么呢,最终最短路径大部分都是通过计算得到而存储下来直接使用的,我觉得它和mysql视图有点像的,视图是一个虚表在实表上计算获得的,但是计算之后各个数据就可以直接使用,floyd是在原本的路径图中通过一个动态规划的策略计算出来点点之间的最短路径。
floyd和dijkstra是经典的最短路径算法,两者有相似也有不同。在复杂度上,dijkstra算法时间复杂度是o(n2),floyd算法时间复杂度是o(n3);在功能上,dijkstra是求单源最短路径,并且路径权值不能为负,而floyd是求多源最短路径,可以有负权值;算法实现上,dijkstra 是一种贪心算法实现起来较复杂,floyd基于动态规划实现简单;两个作者dijkstra和floyd都是牛逼轰轰的大人物,都是图灵奖的获得者。
除了floyd算法,堆排序算法heapsort也是floyd大佬发明的,属实佩服!
floyd算法,俗称插点法,不就一个点一个点插进去更新用到被插点距离嘛!
好啦,floyd算法就介绍到这里,如果对你有帮助,请动动小手点个赞吧!蟹蟹。
国芯思辰|安森德DC-DC同步降压转换器ASP9430可替代台湾致新G5134用于扫地机器人系统
基于simulink的永磁同步电机数学建模仿真设计
华为mate10上市时间确认:华为Mate10发布在即,华为mate9和华为P10这两款真旗舰狂跌超千元
与行业基准 AMB 基板相比,TCFB 的性能如何?
基于一种信号耦合来实现阻抗控制的设计方案
Floyd如何求图的最短路径
消费者出行体验需求多样化 中国车企需从多维度打造智能化
PCB材料的用途/特性与注意事项
r7 4800h和i7 10750h哪个好?买游戏本首选靠谱的英特尔
PCB抗干扰设计
基于单片机的数字多用表的设计
美国拟扩大技术出口限制 含AI机器人等14个科技类别
基于网络技术的可视对讲系统特点及优势
加州圣地亚哥空间探测机器人简介
梅卡曼德机器人获投资 正朝着改造场景的方向努力
物联网平台的2016之战
智能家居系统中的智能魔镜显示屏,它有哪些功能
金属材料检测:从元素到化学成分的全面洞察
一个成功的人工智能项目有那八个关键角色
智能压力传感器的基本功能