区间类动态规划是一种比较特殊的动态规划,以区间作为动态规划的阶段,套路性比较强。
怎样的套路?
状态的表示一般都是:设 d p i , j dp_{i,j} dpi,j 为从 i i i 到 j j j 的区间的XXX。
转移的顺序也很固定,基本都是先求小区间,再求大区间。我们甚至可以写出一个区间 DP 的模板:
//初始化
for(int len = 1; len <= n; len++) //枚举区间长度
//len的初始值不一定为1,需要看具体情况
{
for(int i = 1; i + len - 1 <= n; i++) //枚举左端点
{
int j = i + len - 1; //算出右端点
for(int k = i; k < j; k++) //枚举区间的断点
{
//状态转移
}
}
}
但是记住,千万不要记这个! 这只是告诉大家区间动态规划的常见思路——求区间的解时枚举断点,由左右两部分的解合并出该区间的解。
使用情境
区间 DP 的使用情境还是比较明显的:
- 每次都会操作一个区间,或者操作区间的首尾两端;
- 出现了区间的分解、合并等操作(其实分解就是合并的逆操作),所以能将问题分解成两两合并的形式。
总结一句话:题目做多了,看到就自然知道要用区间类动态规划了。
例题
NOI1995 石子合并
我们先解决一下这个问题的简化版本:一本通5.1例1 石子合并
设 d p i , j dp_{i,j} dpi,j 表示把区间 [ i , j ] [i,j] [i,j] 合并成一堆的最小/最大得分。那么求最小得分就是:
d p i , j = min i ≤ k < j { d p i , k + d p k + 1 , j } + s u m j − s u m i − 1 dp_{i,j} = \min_{i \le k \lt j}\{dp_{i,k}+dp_{k+1,j}\} + sum_j - sum_{i - 1} dpi,j=i≤k<jmin{
dpi,k+