Floyd算法为什么只有5行

Floyd~写起来最简单的算法~没有之一!!!然而,理解起来却一点也不简单~
先来看看算法实现:

    for (int k = 0; k < n; k++)
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
                if (d[i][j] > d[i][k] + d[k][j])
                    d[i][j] = d[i][k] + d[k][j];

其中n是顶点数量,d[i][j]表示点i到点j的最短距离,那么问题来了: k是什么鬼?!

要回答这个问题,我们要先看看算法的原理是什么。。。
随便找个Floyd的解释,都会告诉我们Floyd的核心思想是动态规划,
其状态转移方程是: d[i][j] = min(d[i][j], d[i][k] + d[k][j])

受图论影响,大家都明白k也就是图中一个点,但这方程不是松驰操作吗?!
说好的动态规划呢?
代码外层一个for (int k = 0; k < n; k++)搞定了?
特么一脸懵逼好不好!!~

为了解释这个问题,引进一个概念
Ak(i,j) : 表示i到j的路径中,没有索引超过k的点的最短路径
比如, i=1,j=2, k=5,路径可以1->3->2, 1->5->3->2, 但不能是1->6->2
用脚趾头看出,当k=n-1时,Ak(i,j) = d[i][j], 既最短路径

相信大家也都会求 A0(i,j)
所以现在的问题是:怎么由Ak-1(i,j) 推出Ak(i,j) ? 重点来了!!敲黑板!!

这里其实要分情况讨论:
1. 如果 Ak(i,j) 没有经过点k, 那么 Ak(i,j) = Ak-1(i,j)
2. 如果 Ak(i,j) 经过点k, 那么 Ak(i,j) = Ak-1(i,k) + Ak-1(k,j)
所以有:
Ak(i,j) = min(Ak-1(i,j), Ak-1(i,k) + Ak-1(k,j))

于是,我们既然能求 A0(i,j),也就能求出A1(i,j),最后An-1(i,j)

这也就是为什么Floyd最外层是 for (int k = 0; k < n; k++)
d[i][j] = min(d[i][j], d[i][k] + d[k][j]) 既是松驰操作,也是动态规划的状态转移方程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值