码迷,mamicode.com
首页 > 编程语言 > 详细

算法导论精华总结 ~ 动态规划

时间:2017-02-06 00:06:39      阅读:212      评论:0      收藏:0      [点我收藏+]

标签:return   价格   额外   通过   bottom   log   顺序   问题解决   div   

  解释:动态规划(dynamic programming)与分治方法相似,都是通过组合子问题的解来求解原问题。

  优点:动态规划比分治方法高明之处在于对每个子子问题只求解一次,将其保存,无需重新计算。

  动态规划设计步骤:

    1. 刻画一个最优解的结构特征。
    2. 递归地定义最优解的值。
    3. 计算最优解的值,通常再用自底向上的方法。(维护一些额外信息,以便构造步骤4)
    4. 利用计算出的信息构造一个最优解。

钢条切割问题

  描述:给定一段长度为n英寸的钢条和一个价格表Pi(i = 1,2,...,n),求切割钢条的方案,使得销售收益Rn最大。

  价格表:

    长度i    1    2    3    4    5    6    7    8    9    10

    价格Pi    1    5    8    9    10  17  17   20  24  30

  

  我们可以明显看出来

    R1 = 1,切割方案1 = 1(无切割)

    R1 = 5,切割方案2 = 2(无切割)

    R1 = 8,切割方案3 = 3(无切割)

    R1 = 10,切割方案4 = 2 + 2

  由此可以总结出来一个公式Rn = max(Pn, R1 + Rn-1, R2 + Rn-2,..., Rn-1 + R1)

  由此可以写出自顶向下的递归实现伪代码

CUT-ROD(P,n)       //P为价格数组[1..n],n为长度为n的最大收益
    if n == 0          //如果n = 0 不会有收益,则返回0
        return 0

    q = -无穷          //把最大收益初始化为负无穷

    for i = 1 to n    //循环1到n的切割方式
        q = max(q,P[i] + CUT-ROD(P,n-i))  //最大收益等于当前收益或切割成n段的收益中的最大值
    
    return q           //返回最大收益

  递归的弊病:你会发现一个问题,这个计算非常的慢,在n=40的情况下,就基本得算好几分钟。之所以效率这么差的原因在于,这个函数反复计算相同的参数的递归调用。即反复求解相同的子问题。

  动态规划的实质:这时候就需要动态规划的出现了,动态规划会仔细安排求解顺序,对每个子问题只求解一次,并将结果保存下来。随后再次需要此子问题的解,只需要找保存的结果,而不必重新计算。因此归根结底,动态规划是付出额外的内存空间来节省计算时间,是典型的时空权衡。

动态规划的两种实现方法

  第一种  带备忘的自顶向下法

  第二种  自底向上法

  第一种仍然是递归,只不过加了一个数组来存储每个子问题的解。

  第二种就是从小问题解决,在逐渐推出大问题,类似于一道题的自然衍生过程。

  

  对于钢条切割的第一种方法伪代码

MEMOIZED-CUT-ROD(P,n)
    let r[0..n] be a new array //新建新的数组r
    for i = 0 to n //初始化r
        r[i] = -无穷
    return MEMOIZED-CUT-ROD-AUX(P,n,r) 


MEMOIZED-CUT-ROD-AUX(P,n,r)
    if r[n] >= 0 //如果r[n] >= 0说明这个切割算过一次,直接返回结果
        return r[n]
    if n == 0 //如果切割条数为0,则返回0
        q = 0
    else 
        q = -无穷 //初始化
        for i = 1 to n
            q = max(q, P[i] + MEMOIZED-CUT-ROD-AUX(P, n-i, r)) //最优切割价格为当前价格或切割数为n-i的价格最大值
    r[n] = q //将最优切割值记录
    return q

  第二种方法的伪代码

BOTTOM-UP-CUT-ROD(P,n)
    let r[0..n] be a new array //新建r数组
    r[0] = 0     //初始化 0切割返回0
    for j = 1 to n  //循环从1条到n条长的最优解
        q = -无穷
        for i = 1 to j //循环从1切割到j切割的最优解
            q = max(q, P[i] + r[j-i]) //最优解q = 当前值或长度为i的价格和长度为j-i的最优解的和的最优值
        r[j] = q //记录最优解
    return q

 

 

  

算法导论精华总结 ~ 动态规划

标签:return   价格   额外   通过   bottom   log   顺序   问题解决   div   

原文地址:http://www.cnblogs.com/SHOR/p/6368828.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!