zoukankan      html  css  js  c++  java
  • 44-Floyd 算法

    概述

    • Floyd算法是一个经典的动态规划算法,是解决任意两点间的最短路径(称为多源最短路径问题)的一种算法
    • 也可以正确处理有向图或负权的最短路径问题
    • Dijkstra ~ Floyd
      • Dijkstra算法
        • 单源最短路径,计算图中某一个顶点到其他顶点的最短路径
        • 选定一个顶点作为出发访问顶点,求出从出发访问顶点到其他顶点的最短路径
      • Floyd算法
        • 多源最短路径,计算图中各个顶点之间的最短路径
        • 每一个顶点都是出发访问顶点,求出从每一个顶点到其他顶点的最短路径

    算法思想

    • 从任意顶点 i 到任意顶点 j 的最短路径不外乎 2 种可能:
      • 直接从顶点 i 到顶点 j
      • 从顶点 i 经过若干个顶点 k 到顶点 j
    • 所以,我们假设 arcs(i, j) 为顶点 i 到顶点 j 的最短路径的距离,对于每一个顶点 k,我们检查 arcs(i, k) + arcs(k, j) < arcs(i, j) 是否成立
      • 如果成立,证明从顶点 i 经顶点 k 再到顶点 j 的路径比顶点 i 直接到顶点 j 的路径短,我们便设置 arcs(i, j) = arcs(i, k) + arcs(k, j)
    • 这样一来,当我们遍历完所有顶点 k,arcs(i, j) 中记录的便是顶点 i 到顶点 j 的最短路径的距离

    算法分析

    • 根据以往的经验,如果要让任意两个顶点(假设从顶点 a 到顶点 b )之间的距离变得更短,唯一的选择就是引入第 3 个顶点(顶点 k),并通过顶点 k 中转(a → k → b)才可能缩短顶点 a 到顶点 b 之间的距离

    • 这时问题便分解为:求取某一个顶点 k,使得经过中转顶点 k 后,使得两点之间的距离可能变短,且还可能需要中转 两个或者多个顶点 才能使两点之间的距离变短

    • 于是,延伸到一般问题:

      • 当不经过任意第 3 个顶点时,其最短路径为初始路径,即下图中的邻接矩阵所示
      • 当只允许经过 1 号顶点时,求两点之间的最短路径该如何求呢?
        • 只需判断 arcs[i][1] + arcs[1][j] 是否比 arcs[i][j] 要小即可
        • arcs[i][j] 表示的是从 i 号顶点到 j 号顶点之间的距离
        • arcs[i][1] + arcs[1][j] 表示的是从 i 号顶点先到 1 号顶点,再从1号顶点到 j 号顶点的路程之和
    • 举例


    • 由于上述代码更新了两点之间经过 1 号顶点的最短距离 arcs[i][j],因此,数组中每两个顶点之间对应距离都是最短的

    • 此时 arcs[i][j] 的结果已经保存了中转 1 号顶点时的最短路径,如果再继续并入 2 号顶点为中转顶点,则是任意两个顶点都经过中转顶点 1 号顶点和 2 号顶点的最短路径

    • 更一般的,继续并入下一个中转顶点一直到 vexCount 个时,arcs[i][j] 的结果保存的就是整个图中两点之间的最短路径了 // DP!

    代码实现

    public class FloydAlgorithm {
    	public static void main(String[] args) {
    		char[] vertexs = { 'A', 'B', 'C', 'D', 'E', 'F', 'G' };
    		int[][] matrix = new int[vertexs.length][vertexs.length];
    		final int N = 65535; // 表示不可以连接
    		matrix[0] = new int[] { 0, 5, 7, N, N, N, 2 };
    		matrix[1] = new int[] { 5, 0, N, 9, N, N, 3 };
    		matrix[2] = new int[] { 7, N, 0, N, 8, N, N };
    		matrix[3] = new int[] { N, 9, N, 0, N, 4, N };
    		matrix[4] = new int[] { N, N, 8, N, 0, 5, 4 };
    		matrix[5] = new int[] { N, N, N, 4, 5, 0, 6 };
    		matrix[6] = new int[] { 2, 3, N, N, 4, 6, 0 };
    		Graph graph = new Graph(vertexs, matrix);
    		graph.show();
    		graph.floyd();
    		System.out.println();
    		graph.show();
    	}
    }
    
    class Graph {
    	int vCount;
    	char[] vertexs;
    	int[][] dis; // 保存距离
    	int[][] pre; // 保存前驱
    	
    	public Graph(char[] vertexs, int[][] dis) {
    		super();
    		vCount = vertexs.length;
    		this.vertexs = vertexs;
    		this.dis = dis;
    		this.pre = new int[vCount][vCount];
    		for(int i = 0; i < vCount; i++)
    			for(int j = 0; j < vCount; j++)
    				pre[i][j] = i;
    	}
    	
    	public void floyd() {
    		int len;
    		for(int k = 0; k < vCount; k++) // k: 中间顶点
    			for(int i = 0; i < vCount; i++) // i: 出发顶点
    				for(int j = 0; j < vCount; j++) { // j: 终点
    					len = dis[i][k] + dis[k][j];
    					if(dis[i][j] > len) {
    						dis[i][j] = len;
    						pre[i][j] = k;
    					}
    				}
    	}
    	
    	public void show() {
    		System.out.print("  ");
    		for(int i = 0; i < vCount; i++)
    			System.out.printf("%8c  ", vertexs[i]);
    		System.out.println();
    		for(int i = 0; i < vCount; i++) {
    			System.out.print(vertexs[i]+"  ");
    			for(int j = 0; j < vCount; j++)
    				System.out.printf("%c(%5d)  ", vertexs[pre[i][j]], dis[i][j]);
    			System.out.println();
    		}
    	}
    }
    
  • 相关阅读:
    Nginx配置文件说明
    http服务区域组网的一种方法
    InetAddress.getLocalHost()返回ip 地址异常听问题
    #!/bin/bash(转)
    ThreadPoolExecutor运转机制详解(转)
    memcache 入门学习资料
    Too many open files 异常
    Java并发编程之ConcurrentHashMap
    Java NIO 选择器(Selector)的内部实现(poll epoll)
    Python 的sub和replace的区别
  • 原文地址:https://www.cnblogs.com/liujiaqi1101/p/12489977.html
Copyright © 2011-2022 走看看