区间动态规划(Interval Dynamic Programming, 简称区间DP)是一种处理区间划分和合并问题的动态规划方法。在区间DP中,我们通常将原问题分解为更小的子问题,这些子问题对应于原问题中不同长度的子区间。通过解决这些子问题,并逐步合并它们的解,我们可以最终得到原问题的解。
区间dp主要解决一个区间内的问题,比如一排石子,将他们两两相邻合并在一起,每次合并消耗的能量为两堆石子数量之和,求最小消耗。
比如{1,2,3,4}
状态方程为:dp[i][j] = min(dp[i][k] + dp[k+1][j] + case) case是两堆石子的总和
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin >> n;
int arr[n + 1];
int sum[n + 1];
int dp[n + 1][n + 1];
memset(arr,0,sizeof arr);
memset(sum,0,sizeof sum);
memset(dp,9999,sizeof dp);
for(int i = 1;i <= n;++i){cin >> arr[i];sum[i] = sum[i-1] + arr[i];dp[i][i] = 0;}
for(int len = 1;len <= n;++len)
{
for(int i = 1;i+len-1 <= n;++i)
{
int j = i+len-1;
for(int k = i;k < j;++k)
{
dp[i][j] = min(dp[i][j],dp[i][k] + dp[k+1][j] + sum[j] - sum[i-1]);
}
}
}
cout << dp[1][n];
return 0;
}
1,因为涉及前缀和计算,所以建议从数组1开始
2,循环一定要从小区间开始循环,因为计算时,大区间会用到小区间,如果直接
for(int i = 1;i <= n;++i)
{
for(int j = i;j <= n;++j)
{
for(int k = i;k < j;++k)
{
dp[i][j] = min(dp[i][j],dp[i][k] + dp[k+1][j] + sum[j] - sum[i-1]);
}
}
}
会造成有的值为0的错误情况
解决这种问题用模拟会更简单一点:
n堆石子,合成一堆一定需要消耗n-1次,那么就遍历最小的消耗合成即可
环的处理
来自:区间 DPhttps://oi-wiki.org/dp/interval/