动态规划算法

《算法导论》15章动态规划对这些要点都做了总结。

动态规划定义https://zh.wikipedia.org/wiki/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92

把原问题分解为相对简单的子问题的方式求解复杂问题的方法,适用于有重叠子问题和最优子结构性质的问题。

动态规划与分治法的区别http://jarg.iteye.com/blog/865117

总结起来,动态规划分解的子问题相互重叠(合并时不会影响其子问题的解,借用算法的稳定性这个概念,分解也需要是稳定的),分治法的子问题相互独立。能够用动态规划解决的问题也可已通过分治法解决,优化了实现策略,不去求解重复问题。

动态规划的本质https://www.zhihu.com/question/23995189/answer/35429905

其核心是拆分,更官方的说法是,状态的定义和状态转移方程的定义。

有一种观点认为备忘或者记录不是动态规划方法的核心,我不这么认为,备忘或者记录正是体现分治的子问题相互重叠,是动态规划实现机制中的重要一步。

动态规划为什么叫动态规划:

随着问题规模的变化,问题的最优方案是动态变化的。如求解1,2,7,8,4,5,6……这个序列的最长上升子序列,

问题规模是4时(1,2,7,8)最优方案时1,2,7,8。问题规模时6时(1,2,7,8,4,5)最优方案为1,2,7,8或者1,2,4,5。当问题规模为7时(1,2,7,8,4,5,6)最优方案为1,2,4,5,6。最优方案一直是动态变化的。

应用动态规划方法的4个步骤

1.刻画一个最优解的结构特征;

2.递归地定义最优解的值;

3.计算最优解的值,通常采用自底向上的方法;

4.利用计算出的信息构造一个最优解

动态规划方法求解最优化问题的两个要素:最优子结构和子问题重叠

最优子结构:最优解包含其子结构的最优解。

子问题重叠:如果递归算法反复求解相同的子问题,我们说最优化问题具有重叠子问题 性质。

相关实例:钢条切割问题,矩阵链乘法,最长公共子序列

—————————————————————————————————————————————————————————————————

 钢条切割问题:http://blog.csdn.net/luoshixian099/article/details/46334097

求长度n的最优切割方案(求解n=4)。

问题分析:长度为n的钢条,在n-1个位置选择切还是不切,共有2^(n-1)中方案。

递归方案的选择(a.规模减小;b.遍历;c.简洁):

设最佳收益为r[n],r[n]=max(p[n],r[1]+r[n-1],r[2]+r[n-2],……,r[n-1]+r[1]),最优方案:两个最优子方案之和的遍历

更经典的方案:r[n]=max(p[i]+r[n-i]),1<=i<=n。最优方案:切一刀p[i]后,求剩下的r[n-i]的遍历。

常规的自顶向下递归实现:

CUT-ROD(p,n)//p是价格数组,n是钢条长度。

  1. if  n==0
  2. return 0
  3. q=0//q 代表长度为n时的收益
  4. for i=1 to n
  5. {
  6. q=max(q,p[i]+CUT-ROD(p,n-i))
  7. }
  8. return q

假设n=4时,调用的递归树(CUT-ROD(p,n),中函数调用的次数为2^n)


动态规划问题求解这个问题

加入备忘机制的自顶向下方法

MEMOIZED-CUT-ROD(p,n)

  1. let r[0……n] be a new array
  2. for i = 0 to n
  3. {
  4. r[i]=-1
  5. }
  6. retrun MEMOIZED-CUT-ROD-AUX(p,n,r)

MEMOIZED-CUT-ROD-AUX(p,n,r)

  1. if r[n]>=0
  2. return r[n]
  3. if n==0
  4. {
  5. q=0
  6. }
  7. else
  8. {
  9. q=-FFFF
  10. }
  11. for i =1 to n
  12. {
  13. q=max(q.p[i]+MEMOIZED-CUT-ROD-AUX(p,n-i,r)
  14. }
  15. r[n]=q
  16. return q

自底向上的求解方法(并且记录切割方案)

EXTENDED-BOTTOM-UP-CUT-ROD(p,n)

  1. let r[0……n] and s[0……n] be new arrays
  2. r[0]=0
  3. for j = 1 to n
  4. {
  5. q = -FFFF
  6. for i = 1 to j
  7. {
  8. if q<p[i]+r[j-i]
  9. {
  10. q=p[i]+r[j-i]
  11. s[j]=i
  12. r[j]=q
  13. }
  14. }
  15. }
  16. return r and s

 





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值