zoukankan      html  css  js  c++  java
  • 最短路最基本算法———Floyd算法

    关于floyd算法

    1. 算法简介
    2. 实现思想
    3. 核心代码
    4. 后记

    一、floyd简介
    引自百度百科

    在计算机科学中,Floyd-Warshall算法是一种在具有正或负边缘权重(但没有负周期)的加权图中找到最短路径的算法。算法的单个执行将找到所有顶点对之间的最短路径的长度(加权)。 虽然它不返回路径本身的细节,但是可以通过对算法的简单修改来重建路径。 该算法的版本也可用于查找关系R的传递闭包,或(与Schulze投票系统相关)在加权图中所有顶点对之间的最宽路径。

    是不是觉得很高深?没错,这段介绍并没有什么多大的用。

    换而言之
    floyd就是一种求最短路的算法,最基础的算法
    优点: 代码简短,易于理解,可用于负边权,可求所有点之间的距离
    缺点: 时间复杂度爆炸

    实现思想
    其实floyd是利用dp的思想实现的,不断寻找中间点求最优解

    枚举起始点,中点和终点,利用中点不断对不同的起点终点进行松弛操作,
    更新任意两点之间的最优子答案,最后得到最优解

    核心代码

    for(int k=1;k<=n;k++)//枚举中点 
    {
    	for(int i=1;i<=n;i++)//枚举起点 
    	{
    		for(int j=1;j<=n;j++)//枚举终点 
    	    {
        	    if(i!=j&&i!=k&&j!=k) //三点不是相同的点时
    	    	dis[i][j]=min(dis[i][k]+dis[k][j],dis[i][j]);//利用中点进行松弛操作
    	    }
    	}
    }
    

    是不是很easy?

    当然并不是

    你是否发现,或者有疑问,floyd的操作,如何能保证能得到最优解,而不是被埋没在次优解里,
    或者说你疑问为什么最外层循环是枚举k,因为这样才能保证这个算法的正确性

    还记得开始的介绍的实现思想么
    没错,动态规划
    我们设dis[k][i][j]dis [ k ] [ i ] [ j ] 表示iijj之间可以通过编号为1…k的节点的最短路径。
    那么则dis[k][i][j]dis[k1][i][j]dis [ k ] [ i ] [ j ] 可以从dis [ k -1 ] [ i ] [ j ]转移来,表示iijj不经过kk这个节点。
    也可以从dis[k1][i][k]+dis[k1][k][j]dis [ k - 1 ] [ i ] [ k ] + dis [ k - 1 ] [ k ] [ j ] 转移过来,表示经过k这个点。
    意思即dis[k][i][j]=min(dis[k1][i][j],dis[k1][i][k]+dis[k1][k][j])dis [ k ] [ i ] [ j ] = min ( dis [ k - 1 ] [ i ] [ j ] ,dis [ k - 1 ] [ i ] [ k ] +dis [ k - 1 ] [ k ] [ j ] )
    然后我们能发现我们能dis的第一维k是可以省略的,因为k只和k-1有关(就和背包问题中0/1背包和完全背包的一维优化一个原理)

    所以当前的dis[i][j]dis [ i ] [ j ] 都应该是完成上一层动态规划的,如果k不是在最外层,那么dis[i][j]dis [ i ] [ j ] 就不是完成上一层动态规划的后的状态,有可能有的点没有经过k-1这个点的松弛。

    所以k要放在最外面

    floyd虽然是最短路算法中最简单基础的一个,但永远不要小看任何一个算法,每种算法都有着自己的智慧

  • 相关阅读:
    8. Django系列之上传文件与下载-djang为服务端,requests为客户端
    机器学习入门15
    机器学习入门14
    机器学习入门13
    机器学习入门12
    ML
    AI
    机器学习入门11
    机器学习入门10
    机器学习入门09
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/10366536.html
Copyright © 2011-2022 走看看