文章目录
一、区间dp问题
1.问题概念:区间上进行动态规划,求解一段区间上的最优解。主要是通过合并小区间的 最优解进而得出整个大区间上最优解的dp算法(其与线性dp有很多并通之处,可以通过对问题先进行常规思考,再转化为通过线性dp求解思路思考,最后转化成区间dp)
2.求解问题的思路:划分思路(大区间划分为小区间),求解每个小区间上的最优解,最后再合并成大区间的最优解
3.具体实现方法:枚举区间长度len为每次分割成的小区间长度(由短到长不断合并),内层枚举该长度下可以的起点,自然终点也就明了了。然后在这个起点终点之间枚举分割点,求解这段小区间在某个分割点下的最优解
4.模板代码:
for(int len = 1;len<=n;len++){//枚举长度
for(int j = 1;j+len<=n+1;j++){//枚举起点,ends<=n
int ends = j+len - 1;
for(int i = j;i<ends;i++){//枚举分割点,更新小区间最优解
dp[j][ends] = min(dp[j][ends],dp[j][i]+dp[i+1][ends]+something);
}
}
}
5.三种模型
(1)石子合并模型(线性、圆形)(利用每个分割点来把大区间问题化为小区间问题)
(2)括号匹配模型(宴会穿礼服问题)
(3)抽卡片模型(不需要枚举区间,此类型只和左右边界有关系)
二、背包0-1问题
1.问题描述:有N件物品和一个容量为V的背包。第i件物品的费用(即体积,下同)是w[i],价值是val[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大
2.解题思路:利用动态规划,阶段就是“物品的件数”,状态就是“背包剩下的容量”,那么很显然f [ i , v ] 就设为从前 i 件物品中选择放入容量为 v 的背包最大的价值。那么状态转移方程为:
f[i][v]=max{ f[i-1][v],f[i-1][v-w[i]]+val[i] }
状态转移方程解释:只考虑子问题“将前 i 个物品放入容量为 v 的背包中的最大价值”那么考虑如果不放入 i ,最大价值就和 i 无关,就是 f[ i - 1 ][ v ] , 如果放入第 i 个物品,价值就是 f[ i - 1][ v - w[i] ] + val[ i ],我们只需取最大值即可
3. 空间优化:上述状态表示,我们需要用二维数组,但是这种是可以优化的,考虑到可以对无用值的覆盖,所以只需要一维的滚动数组就可以解决问题,考虑到用f[ v ]来保存每层递归的值,由于我们求f[ i ][ v ] 的时候需要用到的是f[ i-1 ][ v] 和 f[ i-1 ][v - w[i] ] 于是可以知道,只要我们在求f[ v ]时不覆盖f[ v - w[i] ],那么就可以不断递推至所求答案。所以我们采取倒序循环,即v = m(m为背包总容积)
优化代码如下:
for i = 1..N
for v = V..0
f[ v ] = max{ f[ v ],f[ v-w[i] ]+val[ i ] };
另外:对数字位数(值)过大的情况(即超限),导致无法输入时,可以将变量定义为long long类型,也可以定义为字符串数组进行整体输入与输出
三、总结感悟
通过这周的学习,以及对一些经典例题的熟悉,思考编写;掌握了某些区间dp问题是和线性dp存在相同的关系,思考问题的思路基本一致,差别是在解决问题的方法上,具体区别如下:
线性dp:在一条直线上解决问题,对一条直线上的点(可以是一维的线性点,也可以二维的表格点)分析,找出他们的状态,以及与前后一些点的关系(状态转移方程)
区间dp:在线性dp的基础上,将多个点集中化,分析一个小区间上的点,即分析一些连续的点
其次,对于背包问题也有一定的了解(问题的描述可能与之前所学习过的贪心有一定的相似,但是在解决方法上截然不同)
背包问题贪心解决:一般都是可分割的物品,或者是存在装不满的情况(按照性价比装入,但最终实现不了最优化的结果)
背包问题动态规划解决(循环嵌套数永远比最优化的dp记录数组维数多1):物品不可分割,主要是分析第i件物品的选择(选与不选),其次是尤其需要注意其初始化时的细节:
(1)要求恰好装满背包,那么在初始化时除了 f[0] 为 0 其它 f[1…V] 均设为 - ∞,这样就可以保证最终得到的 f[N] 是一种恰好装满背包的最优解
(2)如果并没有要求必须把背包装满,而是只希望价格尽量大,初始化时应该将 f[0…V] 全部设为 0
理解:初始化的 f 数组事实上就是在没有任何物品可以放入背包时的合法状态。如果要求背包恰好装满, 那么此时只有容量为 0 的背包可能 被价值为 0 的 nothing “恰好装满”,其它容量的背包均没有合法的解,属于未 定义的状态,它们的值就都应该是 - ∞了。如果背包并非必须被装满,那么任何 容量的背包都有一个合法解“什么都不装”,这个解的价值为 0,所以初始时状 态的值也就全部为 0 了