区间DP
先计算出小区间的最优解,再去得到大区间的最优解。设f[i][j]为区间[i,j]的最优解。
合并果子
有n堆果子,每堆果子有a[i]个,合并时只能合并相邻两堆,产生的代价为两堆果子的总数,经过n-1次后合并为一堆,求总代价最下
3
1 2 3
output:
9
f[i][j]表示合并[i,j]这个区间产生的最小代价。因为有两堆合并成一堆,枚举分界线i<=k<=j,分为[i,k],[k+1,j],a的前缀和sum
f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+sum[j]-sum[i-1])
(1)记忆化DP
int dp(int i.int j)
{
if(i==j) return 0;
if(f[i][j]!=-1) return f[i][j];
int ans=0x3f;
for(int k=i;k<=j;k++)
f[i][j]=min(f[i][j],dp(i,k)+dp(k+1,j)+sum[j]-sum[i-1]);
return ans=f[i][j];
}
(2)直接DP
要先计算小区间
for(int len=2;len<=n;len++) 保证先计算小区间
{
for(int i=1;i+len-1<=n;i++)
{
int j=i+len-1;
for(int k=i;k<j;k++)
f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+sum[j]-sum[i-1]);
}
}
括号匹配
f[i][j]表示区间[i,j]中的最长子序列
如果s[i]和s[j]能够匹配。那么f[i][j]=f[i+1][j-1]+2,另外[i,j]的答案 也可以有两个子区间的答案合并得来。f[i][j]=max(f[i][j],f[i][k]+f[k+1][j])
for(int len=2;len<=n;len++)
{
for(int i=1;i+len-1<=n;i++)
{
int j=i+len-1;
if(s[i]=='(' && s[j]==')' || s[i]=='[' && s[j]==']')
f[i][j]=f[i+1][j-1]+1;
for(int k=i;k<j;k++)
f[i][j]=max(f[i][j],f[i][k]+f[k+1][j]);
}
}