1.定义
区间DP,顾名思义是在区间上DP,它的主要思想就是先在小区间进行DP得到最优解,然后再利用小区间的最优解合并求大区间的最优解。
2.一般实现代码
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方程实现
}
}
3.经典例题
石子合并一条直线上有N堆石子,现在要将所有石子合并成一堆,每次只能合并相邻的两堆,合并花费为新合成的一堆石子的数量,求最小的花费。
1堆,花费为0
2堆,花费为sum[2]
3堆,花费为min(a[1] + a[2], a[2] + a[3]) + sum[3]
如果我们有n堆,合并的最后一次操作一定是从两堆合并成一堆.
规定dp[i][j]为合并第i堆到第j堆的最小花费
DP方程为:
dp[i][j] = min(dp[i][k] + dp[k+1][j]) + sum[j] - sum[i-1] (i <= k < j)
实现代码如下:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int f[101][101];
int sum[101];
int main()
{ int n,i,j,k,x;
cin>>n;
for(i=1;i<=n;i++)
{
cin>>x;
sum[i]=sum[i-1]+x;
}
memset(f,127,sizeof(f));
for(i=1;i<=n;i++)
f[i][i]=0;
for(i=n-1;i>=1;i--)
for(j=i+1;j<=n;j++)
for(k=i;k<=j-1;k++)
f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+sum[j]-sum[i-1]);
cout<<f[1][n]<<endl;
return 0;
}
感觉区间DP比普通的DP又升级了一下,比较难理解,这两天自己也正找一些例题去理解,最后感觉还不是很透彻,接下来继续努力吧。