一.区间dp
区间DP主要是把一个大区间拆分成几个小区间,先求小区间的最优值,然后合并起来求大区间的最优值,以我现在看的题量对区间dp的总结可能还不太完善,下面写一下我理解的dp:
dp[i][j]一般就代表在从i到j完成这个工作,的最优解,别想太多。
dp[i][j]代表了从i到j的一个区间,这样就既表示了长度,又表示了位置。非常形象,好理解,也方便调用。
区间dp推导解的思路:从最小的区间开始,逐步变大,直到求出最大区间最优值。在变大的过程中,之前 所有长度,所有位置的小区间最优值,都已被求出,依赖之前所有已经求出来的小区间最优值,推导大区间的最优值,最后得到整个区间的最优值的过程,有一定的套路可寻。
下面是一般区间DP实现代码
memset(dp, 0x3f, sizeof(dp));
for (int i = 1; i <= n; i++) //区间长度为1的初始化
dp[i][i] = 0;
for (int len = 2; len <= n; len++) //枚举区间长度
{
for (int i = 1, j = len; j <= n; i++, j++) //区间[i,j]
{
//DP方程实现
}
}
我对区间dp三种模型的理解
前两种模型不同的地方就在于第三重循环,第三种是最简单的模型。
1.合并石子模型
对于每一个要求的区间dp[i][j],在不同的位置分割此区间,结果不相同,因此要在这个区间里枚举所有从i到j的所有的情况,求出最大值或最小值。
for (int i = 1; i <= n; i++)
dp[i][i] = 0;
for (int len = 2; len <= n; len++)
{
for (int i = 1, j = len; j <= n; i++, j++)
{
for (int k = i; k < j; k++)
if(dp[i][j] > dp[i][k] + dp[k+1][j] + sum[j] - sum[i-1])
dp[i][j] = dp[i][k] +dp[k+1][j] + sum[j] - sum[i-1];
}
}
第三重循环为枚举的过程
for (int k = i; k < j; k++)
if(dp[i][j] > dp[i][k] + dp[k+1][j] + sum[j] - sum[i-1])
dp[i][j] = dp[i][k] +dp[k+1][j] + sum[j] - sum[i-