区间动态规划
开始学习动态规划进阶了,不过感觉这个难度有点超NOIP省赛的难度了。。。算了,反正都买了,还是学吧。。。
1.概述
区间 DP:是指在一段区间上进行的一系列动态规划。
对于区间 DP 这一类问题,我们需要计算区间[1,n] 的答案,通常用一个二维数组 dp表示,其中 dp[x][y] 表示区间 [x,y]。
2.一般套路
有些题目,dp[l][r] 由 dp[l][r−1] 与 dp[l+1][r] 推得;也有些题目,我们需要枚举区间 [l,r] 内的中间点,由两个子问题合并得到,也可以说 dp[l][r] 由 dp[l][k] 与 dp[k+1][r]dp[k+1][r]dp[k+1][r] 推得,其中 l≤k< r。
对于长度为 n 的区间 DP,我们可以先计算 [1,1],[2,2]…[n,n] 的答案,再计算 [1,2],[2,3]…[n−1,n],以此类推,直到得到原问题的答案。
3.下面给出枚举中间点的代码模版:
for (int l=2;l<=n;l++){
int en;
for(int st=1;st<=n-l+1;st++){
en=st+l-1;
for(int k=st+1;k<en;k++){
if(dp[st][k-1]*dp[k+1][en]+a[k]>dp[st][en]){
dp[st][en]=dp[st][k-1]*dp[k+1][en]+a[k];
root[st][en]=k;
}
}
if(dp[st][en-1]+a[en]>dp[st][en]){
dp[st][en]=dp[st][en-1]+a[en];
root[st][en]=en;
}
if(dp[st+1][en]+a[st]>dp[st][en]){
dp[st][en]=dp[st+1][en]+a[st];
root[st][en] = st;
}
}
}
值得注意的是:
1.必须先枚举区间长度l否则会炸。
2.注意枚举顺序为长度=>起始点=>中间点,起始点循环开始后马上算终止节点,边界的节点应该在枚举中间节点的循环之外进行!