floyd算法与动态规划

PS:本文是在他人博文基础上加以修改而来,将从 Ak(i,j) 推导 Ak-1(i,j) 改为从 Ak-1(i,j) 推导 Ak(i,j),为的是符合自己的思维习惯,更好的理解floyd算 法,并且方便以后查看。

在此首先对原作者表示感谢!

原文地址——http://blog.csdn.net/roofalison/article/details/5651806


下面进入正文

    floyd的代码实现其实很简单:    

[cpp]  view plain copy
  1. void floyd()  
  2. {  
  3.     for(k=0;k<n;k++)  
  4.         for(i=0;i<n;i++)  
  5.             for(j=0;j<n;j++)  
  6.                 A[i][j]=min(A[i][j],A[i][k]+A[k][j]);  
  7. }  

    floyd算法是一个经典的动态规划算法,目标是寻找从点i到点j(图中任意两点)的最短路径。从动态规划的角度看问题,我们需要为这个目标重新做一个诠释(这个诠释正是动态规划最富创造力的精华所在)。假设图有n个顶点,依次为0,1,,n-1floyd算法加入了这个概念

    Ak(i,j):表示从顶点i到顶点j且中间顶点的序号不大于K的最短路径

    这个限制的重要之处在于,它将最短路径的概念做了限制,使得该限制有机会满足迭代关系,这个迭代关系就在于研究:假设Ak-1(i,j)已知,是否可以借此推导出Ak(i,j)。针对此问题,采用数学归纳法,我们分两步解决:

   1、由Ak(i,j)的定义可得初始状态(即中间不经过其他任何顶点):A-1(i,j) = cost(i,j)。(cost(i,j)为连接顶点i 和顶点j 的边的权值,若两顶点间无边,则值为无穷大)

    2、假设此时Ak-1(i,j)已知,并且在此基础上求解Ak(i,j),那么我们可以分两种情况来看待这个问题:1. Ak(i,j)沿途经过点k;2. Ak(i,j)不经过点k。如果经过点k,那么很显然,Ak(i,j) = Ak-1(i,k) + Ak-1(k,j)。为什么是Ak-1呢?因为Ak-1是我们目前得到的最优解那么遇到第二种情况,Ak(i,j)不经过点k时,由于没有经过点k,所以根据概念,可以得出Ak(i,j)=Ak-1(i,j)。现在,我们确信有且只有这两种情况---不是经过点k,就是不经过点k,没有第三种情况了,条件很完整,那么是选择哪一个呢?很简单,求的是最短路径,当然是哪个最短,求取哪个,故得出式子:

    Ak(i,j) = min( Ak-1(i,j), Ak-1(i,k) + Ak-1(k,j) )

    到这里,已经列出了求取Ak(i,j)的整个算法了,但是,最终的目标是求dist(i,j),即i到j的最短路径,如何把Ak(i,j)转换为dist(i,j)?这个其实很简单,当k=n-1(n表示图中顶点的个数)的时候,即是说,An-1(i,j)=dist(i,j)。那是因为当k已经最大时,已经不存在索引比k大的点了,那这时候的An-1(i,j)其实就已经是顶点i 到顶点j 的最短路径了。

    从动态规划算法设计的角度来讲,求解决策过程的最优化问题,首先应将待求解问题分解成若干个子问题,确定待求解问题与子问题的定量关系,先求解子问题,然后从这些子问题的解得到原问题的解。本文可看做求解定量关系部分(即由子问题出发,求解原问题)。

    个人总结:划分的过程是从上往下,求解的过程是从下往上。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值