本文参考http://blog.csdn.net/ochangwen/article/details/50730937,
1.定义概览
Floyd-Warshall算法(Floyd-Warshall algorithm)又称为插点法是解决任意两点间的最短路径的一种算法,可以正确处理有向图或负权的最短路径问题,同时也被用于计算有向图的传递闭包。Floyd-Warshall算法的时间复杂度为O(N3),空间复杂度为O(N2)。
2.算法描述:
1)算法思想原理:
Floyd算法是一个经典的动态规划算法。用通俗的语言来描述的话,首先我们的目标是寻找从点i到点j的最短路径。从动 态规划的角度看问题,我们需要为这个目标重新做一个诠释(这个诠释正是动态规划最富创造力的精华所在), 从任意节点i到任意节点j的最短路径不外乎2种可能,1是直接从i到j,2是从i经过若干个节点k到j。所以,我们假设
Dis(i,j)为节点u到节点v的最短路径的距离,对于每一个节点k,我们检查Dis(i,k) + Dis(k,j) < Dis(i,j)是否成立,如果成立,证明从i到k再到j的路径比i直接到j的路径
短,我们便设置Dis(i,j) = Dis(i,k) + Dis(k,j),这样一来,当我们遍历完所有节点k,Dis(i,j)中记录的便是i到j的最短路径的距离。
2).算法描述:
a.从任意一条单边路径开始。所有两点之间的距离是边的权,如果两点之间没有边相连,则权为无穷大。
b.对于每一对顶点 u 和 v,看看是否存在一个顶点 w 使得从 u 到 w 再到 v 比己知的路径更短。如果是更新它。
3).Floyd算法过程矩阵的计算----十字交叉法
补充其中用到的十字交叉法如下:
先来简单分析下,由于矩阵中对角线上的元素始终为0,因此以k为中间点时,从上一个矩阵到下一个矩阵变化时,矩阵的第k行,第k列和对角线上的元素是不发生改变的(对角线上都是0,因为一个顶点到自己的距离就是0,一直不变;而当k为中间点时,k到其他顶点(第k行)和其他顶点到k(第k列)的距离是不变的)。
因此每一步中我们只需要判断4*4-3*4+2=6个元素是否发生改变即可,也就是要判断既不在第k行第k列又不在对角线上的元素。具体计算步骤如下:以k为中间点(1)“三条线”:划去第k行,第k列,对角线(2)“十字交叉法”:对于任一个不在三条线上的元素x,均可与另外在k行k列上的3个元素构成一个2阶矩阵,x是否发生改变与2阶矩阵中不包含x的那条对角线上2个元素的和有关,若二者之和小于x,则用它们的和替换x,对应的Path矩阵中的与x相对应的位置用k来替代。。。
具体实例及代码如下所示:
/** * @Title: Floyd.java * @Package dynamicprogramming * @Description: TODO * @author peidong * @date 2017-6-13 上午9:23:39 * @version V1.0 */ package dynamicprogramming; /** * @ClassName: Floyd * @Description: 弗洛伊德最短路径算法 * @date 2017-6-13 上午9:23:39 * */ public class Floyd { public static void shorestFloyd(){ int MAX_VALUE = 65535; int[][] edgesMatrix ={{0, 5, MAX_VALUE, 7}, {MAX_VALUE, 0, 4, 2}, {3, 3, 0, 2}, {MAX_VALUE, MAX_VALUE, 1, 0}}; int n = 4;//vertexSize; 结点个数 int[][] tc = new int[n][n]; //保存从i到j的最短路径值 int[][] p = new int[n][n]; //保存经过的中间结点 //初始化tc,p for(int i = 0; i < n; i++){ for(int j = 0; j < n; j++){ p[i][j] = -1; tc[i][j] = edgesMatrix[i][j]; //便矩阵 } } //进行Floyd算法,从0到n-1所有可能进行遍历 for(int x = 0; x < n; x++){ //x表示中间结点 for(int i = 0; i < n; i++){ for(int j = 0; j < n; j++){ if(tc[i][j] > tc[i][x] + tc[x][j]){ tc[i][j] = tc[i][x] + tc[x][j]; p[i][j] = x; } } } } // 下面对获得的结果进行展示 System.out.println("最短路径状态转移矩阵为:"); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { System.out.print(" " + tc[i][j]); } System.out.println(); } System.out.println("对应的结点矩阵为:"); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { System.out.print(" " + p[i][j]); } System.out.println(); } // System.out.println("+++++++++++++++++++++++++++++++++++"); /* for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { System.out.println("输出i=" + i + "到j=" + j + "最短路径:"); int k = p[i][j]; if (k == -1) { System.out.println("没有最短路径"); } else { System.out.print(" " + k); while (k != j) { k = p[k][j]; System.out.print(" " + k); } System.out.println(" "+k); System.out.println(); } } } */ } /** * @Title: main * @Description: 测试用例 * @param args * @return void * @throws */ public static void main(String[] args) { // TODO Auto-generated method stub shorestFloyd(); } }