动态规划

本文探讨了动态规划的基本原理及其在解决钢条切割问题中的应用。通过介绍最优子结构特性,阐述了如何避免重复计算子问题,提高算法效率,并展示了具体的实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

分治法:将问题划分为互不相交的子问题,递归地求解子问题,再将它们的解组合起来
动态规划:子问题重叠;通常用于求解最优化问题
    分治法会做许多重复工作,反复求解公共子问题;而动态规划则对每个子问题只求解一次并保存下来

步骤:
    1) 刻画一个最优解的结构特征
    2) 递归地定义最优解的值
    3) 计算最优解的值,通常采用自底向上的方法
    4) 利用计算出的信息构造一个最优解【如果只是求最优解的值则不需要这一步】

最优子结构性质:问题的最优解由相关子问题的最优解组合而成,且这些子问题能独立求解

钢条切割问题:一根长为n英寸的钢条,其对应长度i有一个售价pi,求如何切割使得售价最高。
    设最佳收益为rn,则
    1. rn = max{pn, r1 + rn-1, r2 + rn-2, ..., rn-1 + r1}
    从而钢条切割问题满足最优子结构性质
    2. 也可以降钢条从左边切割下长度为i的一段,对右边剩下的长度为n-i的一段继续进行切割,对左边的一段则不再进行切割
        rn = max(pi + rn-i)        i = 1, ..., n
        CUT-ROD(p, n)
            if n == 0
                return 0
            q = inf
            for i=1 to n
                q = max(q, p[i] + CUT-ROD(p, n-i))
            return q
        性能差,随着n每次增大1,程序运行时间增长1倍;因为其反复求解重复的子问题
    3. 根据上面的方法,每次将子问题的解保存下来,不必重新计算;典型的空间换时间
        1) 带备忘的自顶向下法,过程保存每个子问题的解,当需要一个子问题的解时,先检查是否已经保存过此解
        2) 自底向上法,需要恰当定义子问题“规模”的概念,使得任何子问题的求解都只依赖于“更小的”子问题的求解
            BOTTOM-UP-CUT-ROD(p, n)
                let r[0..n] be a new array
                r[0] = 0
                for j=1 to n
                    q = inf
                    for i=1 to j
                        q = max(q, p[i] + r[j-i])
                    r[j] = q
                return r[n]
    重构解,上面得到的只是最优解的收益值,而没有得到最优解本身(即切割方案)
    下面的扩展,s保存了解规模为j的子问题时,第一段钢条的最优切割方案s[j];得到s[j]将其打印出来即可【PP209】
        
            EXTEND-BOTTOM-UP-CUT-ROD(p, n)
                let r[0..n], s[0..n] be a new array
                r[0] = 0
                for j=1 to n
                    q = inf
                    for i=1 to j
                        if q < p[i] + r[j-1]
                            q = p[i] + r[j-i]
                            s[j] = i
                    r[j] = q
                return r and s
            PRINT-CUT-ROD-SOLUTION(p, n)
                (r, s) = EXTEND-BOTTOM-UP-CUT-ROD(p, n)
                while n > 0
                    print s[n]
                    n = n - s[n]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值