Floyd算法--简单易懂版

参考链接:https://www.cnblogs.com/wangyuliang/p/9216365.html,非常棒!!!

Floyd(弗洛伊德)算法前言:以图形化的方式呈现问题

   

 思路:

1.以矩阵的结构来存储图的信息,本身点间的距离为0,两点间无直达路径距离为∞

            

 2.想缩短a、b两点间距离,只能引入第三个点k,甚至更多点,使得a->k->b、a->k1->k2…->k->i…->b能有更短距离

      假如现在只允许经过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和2号两个顶点的情况下任意两点之间的最短路程

//经过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,实质在更新2时,已经确定了a->1->2->b的最近距离,所致只需要逐一更新所有中间点,就遍历了所有a->k1->k2…->k->i…->b的可能场景,最终得到的必然是最优值)

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

 
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号点的最短路程

 注意:Floyd-Warshall算法不能解决带有“负权回路”(或者叫“负权环”)的图,因为带有“负权回路”的图没有最短路,永远找不到最短路。   

         

posted @ 2021-10-14 00:21  行路人&  阅读(110)  评论(0编辑  收藏  举报