动态规划DP算法学习笔记 (算法导论第十五章)

本文探讨了动态规划的基本原理及其在解决特定类型问题上的应用。通过分析钢条切割问题和矩阵链乘法问题,展示了如何利用动态规划求解最优解。讨论了动态规划的关键特性:最优子结构与子问题重叠,并介绍了自顶向下与自底向上的求解方法。
摘要由CSDN通过智能技术生成

注:不要随意复制代码,未运行过,就当做 伪代码 看看吧,有错误请留言
[TOC]

一. 引言

  • 动态规划,Dynamic Programming;
    programming指的是一种“表格法”
  • 与分治算法DC的异同
    • 同:都是通过 “组合子问题的解” 来求解原问题
    • 异:对于每个子子问题的处理不同 —— DP只处理一次,并将其解保存在一个表
      格中。而DC没有考虑过子子问题的求解是否重复,DC更适用于互不相交的子问题
  • DP设计步骤:回头再看看
    1. 刻画一个最优解的结构特征
    2. 递归地定义最优解的值
    3. 计算最优解的值,通常“自底向上”
    4. 利用计算出的信息,构造一个最优解

二. 钢条切割问题

Serling公司购买长钢条,将其切割为短钢条出售。切割工序本身没有成本支出。公司管理层希望知道最佳的切割方案。假定我们知道Serling公司出售一段长为i英寸的钢条的价格为pi(i=1,2,…,单位为美元)。钢条的长度均为整英寸。
长度i12345678910
价格pi1589101717202430

钢条切割问题是这样的:给定一段长度为n英寸的钢条和一个价格表pi(i=1,2,…n),求切割钢条方案,使得销售收益rn最大。注意,如果长度为n英寸的钢条的价格pn足够大,最优解可能就是完全不需要切割。

1. 一般的递归算法 O(2n)

int cutRod(int* price, int length)
{
    int maxP = 0;
    if(length == 0)
        return 0;
    for(int i = 0; i < length; i++)
    {
        maxP = max(maxP, 
                    price[i] + cutRod(price + i +1, length - i));
    }
    return maxP;
}

2. 动态规划方法求解 O(n2)

2-1. 带备忘的自顶向下法(top-down with memorization)

  • 创建一个数组或散列表 r[length] ,代表长度为length时的最优解,全部初始化为-1。
  • 在上面的基线条件之前,加入一个判断 r[length]>=0 即可,若true则直接return r[length]

2-2. 自底向上(bottom-up method)

  • 不需要递归,变成了两个嵌套的for循环
int cutRod(int* price, int length)
{
    int r[length + 1]; //这里存在一个问题,可能无法用变量定义数组长度,可改为链表或hash表。r[0]到r[length]。
    r[0] = 0;
    for(int i = 1; i <= length; i++)
    {
        int maxP = -1;
        for(int j = 1; j <= i; j++)
            maxP = max(maxP, price[j] + r[i - j]);//因为 i - j <= i - 1,所以一定已经计算过r[i - j]了。r[i - j]是对应长度i-j的最优解,所以只需分成price[j] 与 r[i - j]这两部分即可
        r[i] = maxP;
    }
    return r[length];
}

三. 矩阵链乘法

1. 相关概念

  • 完全括号化的(fully parent thesized):矩阵乘法满足结合律,由括号完全确定一个矩阵链的相乘顺序
  • 相容(compatible): Apq Bqr 相容,即可以相乘

2. 矩阵链乘法问题(matrix-chain multiplication problem)——描述

给定 n 个矩阵的链<A1,A2,...,An>,矩阵 Ai 的规模为 pi1pi(1in) ,求完全括号化方案,使得乘积 A1A2An 所需标量乘法次数最少

3. 寻找最优括号化方案——最优解

  • 暴力解:穷举
    递归公式略(P221),方案数量与 n 成指数关系
  • 动态规划方法
    1. 寻找最优子结构。从子问题的最优解,逆向构造出,原问题的最优解。(递归思想)
      本题中:找到一个k将区间 [i,j] 分割为两部分,将 AiAj 括号化为 (AiAk)(Ak+1Aj) ,此时k为最优分割点,使得计算次数最小。
    2. 子问题重叠性质。自底向上:第一步就求出所有最小子问题,然后遵循上一步操作即可。
      本题中:按顺序依次求 所有 2矩阵组、3矩阵组、4矩阵组 … n矩阵组的计算次数,小组是大组的子问题,可直接调用。
    3. 本题解法与时间复杂度
      • 3个for循环:1.矩阵链长度length由小到大;2.一定长度下,“window slide”向右滑动,得到所有长度为length的小矩阵链;3.对于当前的小矩阵链,从i到j遍历,找到最佳分割点k∈[i, j)。伪代码见P213
      • O(n3)

四. 动态规划原理总结

满足用 动态规划 求解 最优化 问题的两要素:最优子结构子问题重叠

1. 最优子结构

  • 最优子结构性质:一个问题的最优解,包含其子问题的最优解
  • 子问题无关性质:子问题不相交

2. 重叠子问题

递归算法反复求解相同的子问题时,称该最优化问题具有重叠子问题性质

3. 重构最优解

根据额外维护的表,重构。

4. 备忘

自顶向下方法 = 递归算法 + 备忘机制
有递归调用的开销
注:一般使用自底向上方法,不需要备忘,但也需要维护一个类似的表

添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值