不同于Dijkstra算法,Floyd-Warshall算法可以求出一张图中任意两点的距离。
该算法由1978年图灵奖获得者斯坦福大学计算机科学系教授罗伯特·弗洛伊德命名。

伯特·弗洛伊德先生
图灵奖:作为计算机权威奖项之一,被誉为计算机界的“诺贝尔”奖。截至至2020年11月,姚期智先生是我国唯一一位获此殊荣的计算机科学家。

姚期智先生
算法的核心思想:动态规划。
设置状态:d[k][i][j]的含义是,假如思考的路径包含了k号点(0->k)(注释:未必非要从K顶点走),那么最优的答案是多少呢?
现在,假设所有的之前的状态方案已经转移完成:【k-1】层次的点,那么现在对于【K】的转移:
应该考虑这个问题:(1)不走K顶点,那么就是d[k][i][j]=d[k-1][i][j];(2)走了K顶点:那么状态转移就是d[k][i][j]=d[k-1][i][k]+d[k-1][k][j];
所以最终的状态转移方程是:d[k][i][j]=min(d[k-1][i][j],d[k-1][i][k]+d[k-1][k][j]);
当k=0的时候,那么意思就是直接相连那么这个值就是cost(I,j);(路径上的花费)
现在,如果我们把i,j转化成坐标轴的x轴,y轴,把k化为z轴。
那么在三维的坐标里面。k是从下往上不会突然返回的,那么实际上可以不再考虑k的值,从而直接更新d[i][j]的值,那么就不需要三维数组了。最后的状态转移方程d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
那么现在思考,怎么维护i,j,k之间的关系呢?
假设三重循环是i,j,k的顺序。
从(1,1)(1,2)(1,3)…的顺序开始计算的时候。
那么当(1,3)就应该需要两个(1,2)(2,3)的状态转移过来,显然(2,3)是没有被计算过的。
所以这样的循环是错误的。
实际上,在刚刚设计数组的时候,把三维变成二维的时候,就已经考虑到k是会一直往上的。
那么按照k,i,j的时候来循环,直观的意思就是,当包含了0->k的顶点的时候,d[i][j]的值是多少?
这样的话,上面的错误便完美解决,所以最终循环按照k,i,j来进行即可。(思路上也应该是这样思考)
最终代码实现:(缺少读入和输出)

核心部分的实现
Bilibili同名UP主,CSDN同步更新。

1170

被折叠的 条评论
为什么被折叠?



