计算完全最短路径的Floyd算法

来源:互联网 发布:mac系统偏好设置卡死 编辑:程序博客网 时间:2024/06/01 20:11
Floyd算法可以用于构造无向或有向加权图(不包含长度为负的回路)的完全最短路径:




Floyd算法算法的构造过程非常类似于Warshall算法,所以放在一起讲:

Warshall算法是通过每次加入一个顶点,看把这个顶点作为中间顶点是否能改进传递闭包的矩阵(通过这个新加入的顶点作为中间桥梁,使得原来不可达的2个顶点可

达,以此逐步向传递闭包逼近)。

Floyd算法非常类似,通过初试的权重矩阵,每次加入一个顶点,看这个顶点是否能作为中间顶点改变图的权重矩阵(加入这个中间顶点后,每两个点之间的最短距离

是否减小了)。



伪代码:




实现:

复制代码
package Section8;


/*第八章 动态规划 完全最短路径的Floyd算法*/

public class Floyd {

/**
*
@param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int[][] WeightMat = {
{
0,1000,3,1000},
{
2,0,1000,1000},
{
1000,7,0,1},
{
6,1000,1000,0}
};
int[][] Result = Floyd(WeightMat);

System.out.println(
"输出表达完全最短路径的矩阵:\n");
for(int i = 0;i < Result.length;i++)
{
for(int j = 0;j < Result.length;j++)
System.out.print(Result[i][j]
+ " ");
System.out.println();
}

}

public static int[][] Floyd(int[][] WeightMat){
//接受一个图的权重矩阵,返回表达完全最短路径的矩阵
int n = WeightMat.length;
int[][] Result = WeightMat;

for(int k = 0;k < n;k++) //进行n次变换,每次加入第k个点
{
int[][] temp = new int[n][n];
for(int i = 0;i < n;i++)
for(int j = 0;j < n;j++)
temp[i][j]
= min(Result[i][j],Result[i][k]+Result[k][j]);//加入第k个点后路径是否能缩短
Result = temp;
}

return Result;
}

private static int min(int m,int n){
if(m < n)
return m;
return n;
}

}
复制代码


运行结果:


输出表达完全最短路径的矩阵:

0   10   3   4   
2   0   5   6   
7   7   0   1   

6   16   9   0



例如Floyd算法,我们得到了它的最短路径的值,但具体的最短路径又是哪一条呢?

这也是动态规划问题的一个常见的关键点,我们常见的是求出最优的那个代价,但有时候需要去求得到这个代价的具体路径


于是有下面一道很好的思考题:

Q:加强Floyd算法,使得它能得到最短路径本身,而不仅仅是它的长度。


解答:

可以再弄一个矩阵p(大小为n*n),p[i , j] = k,表明从 i 到 j 的最短路径要经过顶点 k (注意不是只经过 k)。这样在原来的Floyd算法里,每次加入顶点 k 来改

变矩阵时,若 k 起到了作用(加入k后对某个最短路径起到了修正作用),那么就把进行把 k 记在 p 矩阵里:



相比原算法,就是多用了一个p矩阵,加了最后一行,每次加入k起到了作用的时候,记下。注意这个伪代码是空间优化了的Floyd算法,直接在原矩阵上填。

这样最终结果就得到了2个矩阵:D矩阵记录了所有 i 到 j 顶点的最短路径。p矩阵间接表达了每条最短路径的具体路径。例如:最终可能得到下列p矩阵:



根据p[i , j] 的定义, p[1][2] = 3,表明从顶点1(即顶点a)到顶点2(即顶点b)的最短路路径至少要经过顶点3(即顶点c)----见最上面那幅图。

即顶点3是顶点1到2最短路径上的一个桥梁,那么从1到3以及从3到2之间还有没有别的桥梁呢?再看p[1][3] = 0,p[3][2] = 0,所以没有了,那么从1到2的最短

路径就是1,3,2。

下列递归算法可以表明上述过程,来从p矩阵中输出任意两个点之间的最短路径:



注意是递归的,每个k都将 i,j 分开了,为什么可以递归?这里又要说到最优子结构,因为从 i 到 j是最短路径,那么从 i 到 k,以及从 k 到 j也是子问题的最短路

径。


这个问题很重要,注意怎么去记录一个动态规划产生的过程,这样我们最终得到的就不仅仅是一个最优化的代价,还可以得到一个表达这个动态规划解是怎么来的矩

阵。
注意这个矩阵只是表达了生成的过程,要输出具体的解,还需要一个算法从这个矩阵中去挖掘出这个答案

0 0
原创粉丝点击