Floyd算法

3 篇文章 0 订阅
1 篇文章 0 订阅

Floyd最短路算法

当初学这个算法的时候,都说是DP思想……但是当时学的匆匆,具体是怎么个DP法确实不大清楚,但是理解这个东西,一旦出了偏差,代码就会莫名爆炸……

其实对于最短路的算法,最重要的步骤其实就是松弛,比如Dijkstra算法,贪心策略就是,每次让到源点距离最近的那个点,去松弛其他的点。

而弗洛伊德算法的基操也是松弛操作,但和单源最短路径的只松弛源点到其他点的距离不同,Floyd算法每次选取一个点,去松弛其他任意两点的最短路径

具体过程可以描述为这样:

整个过程可分为n个阶段,n为图中点的个数
在阶段 k k k,对于 D P [ k ] [ i ] [ j ] DP[k][i][j] DP[k][i][j],我们可以理解为,已经考虑了前 k k k 个点并使用了第 k k k 个点做松弛后,点 i i i到点 j j j的最短距离
则有转移方程:
D P [ k ] [ i ] [ j ] = m i n ( D P [ k ] [ i ] [ j ] , D P [ k − 1 ] [ i ] [ k ] + D P [ k − 1 ] [ k ] [ j ] ) DP[k][i][j] = min (DP[k][i][j], DP[k - 1][i][k] + DP[k-1][k][j]) DP[k][i][j]=min(DP[k][i][j],DP[k1][i][k]+DP[k1][k][j])

当然,目前看到的算法大多是 D P [ i ] [ j ] = m i n ( D P [ i ] [ j ] , D P [ i ] [ k ] + D P [ k ] [ j ] ) DP[i][j] = min (DP[i][j], DP[i][k] + DP[k][j]) DP[i][j]=min(DP[i][j],DP[i][k]+DP[k][j]),也就是经过了降维。因为对于 D P [ k ] [ i ] [ j ] DP[k][i][j] DP[k][i][j],依赖的历史状态只有 D P [ k − 1 ] [ i ] [ k ] DP[k-1][i][k] DP[k1][i][k] D P [ k − 1 ] [ k ] [ j ] DP[k-1][k][j] DP[k1][k][j],如果我们进行降维,只要保证在更新 D P [ k ] [ i ] [ j ] DP[k][i][j] DP[k][i][j]时, D P [ k − 1 ] [ i ] [ k ] DP[k-1][i][k] DP[k1][i][k] D P [ k − 1 ] [ k ] [ j ] DP[k-1][k][j] DP[k1][k][j]没有被第K阶段更新过即可。

而只有当 k = i k = i k=i k = j k = j k=j 时, D P [ i ] [ j ] = m i n ( D P [ i ] [ j ] , D P [ i ] [ k ] + D P [ k ] [ j ] ) DP[i][j] = min (DP[i][j], DP[i][k] + DP[k][j]) DP[i][j]=min(DP[i][j],DP[i][k]+DP[k][j])中依赖的两个历史状态可能被第K阶段更新,但是…… k = i k = i k=i k = j k = j k=j的情况,其实就等价于并没有引入第三点,也就是单纯的两点间距离(比如 k = i k = i k=i, 则 D P [ i ] [ j ] = m i n ( D P [ i ] [ j ] , D P [ i ] [ i ] + D P [ i ] [ j ] = D P [ i ] [ j ] ) = D P [ i ] [ j ] , DP[i][j] = min (DP[i][j], DP[i][i] + DP[i][j] = DP[i][j]) = DP[i][j], DP[i][j]=min(DP[i][j],DP[i][i]+DP[i][j]=DP[i][j])=DP[i][j],) ,所以即使降了维,算法还是正确的。

既然K表示状态,所以理应在最外层循环……不要学我这个傻傻的把K写在最内层还对程序WA表示一脸懵逼的傻X

code

for(k = 0; k < n; ++ k) { 
	for(i = 0; i < n; ++ i) {
		for(j = 0; j < n; ++ j) {
			if(DP[i][j] > (DP[i][k] + DP[k][j])) {
                 DP[i][j] = DP[i][k] + DP[k][j];
                 path[i][j] = k;//顺便可以记录路径
			}
		}
	}
} 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值