分段dp

题目:洛谷p1338算式

基本分析:这题看似我们可以用区间DP的方式,将数据分左部分,右部分,然后用加号或乘号连接起来,但此时的问题就是每部分允许有多少乘号,
这个又得枚举。所以这样的方法可做,但复杂度要变成O(n3*m2)。那么对于这类分区间时,又对区间内操作数量有限制的DP,我们可以用分段DP的方式,
用dp[i][j]表示前i个数字使用j次乘法得到的最大值。那么起转移就是 dp[i][j]=max{dp[k][j-1]sum(a[i]-a[k])} (sum(a[i]-a[k])表示a[k+1]至a[i]的求和),从而,我们可以用O(n^2m)复杂度解决该问题。

本质就是k决定了必须分成多少段,因此只要枚举某一区间内的乘号个数(即分段数)。
代码:
'''cpp

include

include

using namespace std;
int main()
{
int sum[105] = {}, n, k, dp[105][105] = {}, g;
scanf("%d%d", &n, &k);
for(int i = 1;i <= n;i++)
{
scanf("%d", &g);
if(i == 1) sum[1] = g;
sum[i] = g + sum[i - 1];
}
for(int i = 1;i <= n;i++)
{
dp[i][0] = sum[i];
for(int j = 1;j <= min(i - 1,k);j++)
{
for(int k = 1;k <= i;k++)
{
dp[i][j] = max(dp[i][j],dp[k][j - 1] * (sum[i] - sum[k]));
}
}
}
printf("%d", dp[n][k]);
return 0;
}
'''> ``

posted @ 2021-03-16 20:18  Mint-hexagram  阅读(23)  评论(1编辑  收藏  举报