以前就是觉得这Floyd算法很简单的,不就是三个循环嘛,但是那时候不知道这三个循环究竟是为何的,只是为了考研而把它背下来,不理解,只是觉得Floyd算法很简练,代码就如下几行。
其中,
d[i][j]记录两点间距离,
p[i][j]记录i -> j路径上第二个结点,其实就是第一个非开始结点的结点,
譬如上述图中,p[0][2]=1,因为0->1->2,p[0][1]=1,两点之间一次可达是最小距离的话就是终点。
由此通过p可以记录任意两点的最短路径。
void Floyd_Warshall(int d[maxSize][maxSize],int p[maxSize][maxSize], int n) { int i, j, k; for(i = 0; i < n; ++i) { for(j = 0; j < n; ++j) { p[i][j] = j; } } for(k = 0; k < n; ++k) { for(i = 0; i < n; ++i) { for(j = 0; j < n; ++j) { if(d[i][k]+d[k][j] < d[i][j]) { d[i][j] = d[i][k]+d[k][j];//更新最短距离 p[i][j] = p[i][k];//更新下一跳的点 } } } } }
在对动态规划有了更深一层了解之后,才想起原来这个Floyd算法是自底向上的动态规划算法
Dk(i,j)为从i到j的只以(1..k)集合中的节点为中间節点的最短路径的长度 ,它的状态转移方程
若i,j的最短路径经过k,则Dk(i,j)=Dk-1(i,k)+Dk-1(k,j)
若i,j的最短路径不经过k,则Dk(i,j)=Dk-1(i,j)
现在不知道最短路径是否经过k,我们可以通过比较上述两个大小,知道较小值就是当前最短距离,便可决定是否经过k,
最终Dk(i,j)取上述两种情况的最小值。则Dk(i,j)=min (Dk-1(i,j) , Dk-1(i,k)+Dk-1(k,j))
于是可以根据这转移方程得出自顶下上的动态规划算法,如此就是代码的实现。
本文基于知识共享署名-非商业性使用 3.0 许可协议进行许可。欢迎转载、演绎,但是必须保留本文的署名林羽飞扬,若需咨询,请给我发信