dp入门

本文介绍了动态规划(DP)的基本概念、性质和应用,通过矩阵连乘和01背包问题深入讲解了DP的解题步骤,包括如何刻画最优子结构、递归定义最优解、计算最优解的值以及构建最优解方案。同时,对比了自底向上和自顶向下(备忘录)两种实现方式,并讨论了空间复杂度优化。最后,举例说明了最长公共子序列、最长递增子序列和多重背包问题的DP解决方案。
摘要由CSDN通过智能技术生成

何为dp:

动态规划(dynamic programming),与分治相似的一种算法。

区别:
分治问题性质: 最优子结构

dp问题性质: 最优子结构+重叠子问题

dp通常用来求解最优化问题。问题可能有很多可行解,每个解都有一个值,找出具有最优值的一个(可能有多个)解。

步骤:
1.刻画最优子结构
2.递归定义最优解
3.计算最优解的值 通常自底向上
4.必要的话构建整个最优解方案

例题1: 矩阵连乘

给定n个可以连乘的矩阵序列来计算乘积。由于矩阵乘法满足结合性,存在不同的计算次序。求解所需标量乘法最少的方案,用圆括号表示。  

样例输入:
5
3 4 2 1 6 5
样例输出:
65
((1,(2,3)),(4,5))

分析:
暴力?
方案数:
P(1) = 1;
P(n) = sum{P(k)*P(n-k)}
等于卡特兰数第n-1项 指数级增长

dp思路:
问题的两个性质:
最优子结构、重叠子问题。

1.刻画最优子结构
长度为n的序列,n-1种划分,其最优解由某个划分的最优解构成。

2.构造最优解
f[i,j] = 0 , i == j;
f[i, j] = min{f[i, k] + f[k+1, j] + m[i-1]*m[k]*m[j]} i<=k<=j , i < j

3.计算最优解的值
两种实现

自底向上:

对每个(l, r), 都只需要子区间的最优解,因次可以按区间长度递增进行求解。
长度为1的区间答案为0,长度为2的区间由长度为1的求出,依次类推,直到求出(1, n)。

实现:

    for (int i = 1; i <= n; i++) 
        buf[i][i] = 0; 

    for (int l = 2; l <= n; l++)     
        for (int i = 1; i <= n-l+1; i++) { 
            int j = i + l - 1; 
            buf[i][j] = INF; 
            for (int k = i; k < j; k++) { 
                int sum = buf[i][k] + buf[k+1][j] + m[i-1] * m[k] * m[j]; 
                if (sum < buf[i][j]) { 
                    buf[i][j] = sum; 
                    path[i][j] = k; 
                } 
            } 
        }

自顶向下(备忘录):
分治为什么会超时?因为有大量子问题重复计算。
备忘录解决的办法就是给所有子问题状态打个表。第一次遇到子问题时,计算求解并存表,随后每次遇到这个子问题都只需查表返回就行。

实现:

 int dp(int l, int r) { 
    if (l == r) 
        return 0; 
    if (buf[l][r]) 
        return buf[l][r]; 

    int ans = INF, mini; 
    for (int i = l; i < r; i++) { 
        int sum = dp(l, i) + dp(i+1, r) + m[l-1] * m[i] * m[r]; 

        if (ans > sum) { 
            ans = sum; 
            mini = i; 
        } 
    } 

    path[l][r] = mini; 
    return buf[l][r] = ans; 
}

两者对比:
通常情况下,自底向上要快一些,因为相比备忘录没有递归调用的一些;
某些不需要所有子问题的情况,备忘录要好一些。

4.构建最优解方案
有一个二维数组保存每个区间的分割点,递归即可。

    void print(int l, int r) { 
    if (l
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值