HDU 1024 Max Sum Plus Plus

来源:互联网 发布:小丸压制软件 编辑:程序博客网 时间:2024/06/01 15:05

题目链接:[kuangbin带你飞]专题十二 基础DP1 A - Max Sum Plus Plus

题意

给n个数,将其分为m部分,各部分之间不能有交叉重叠,求最大和

思路

dp[i][j]表示前j个数分为i部分的最大和,则
dp[i][j] = max(dp[i][j-1] + a[j], dp[i-1][k] + a[j]) i-1<=k<=j-1
前者是将第j个数加入到第i部分,后者是将第j个数做为第i部分的第一个数。

两个关键点

  1. 因为题目n值范围过大,显然二维数组不行。
    而d[i][x]只与d[i-1][x]有关,所以可以将其降低至一维。
    即dp[j]表示前j个数所分段后的和。
  2. 因为dp[i-1][k]的取值需要一重循环,极有可能导致超时,所以使用数组max存储当前层的最大值,以供下一层求值使用。
    dp[j] = max(dp[j-1] + a[j], max[j-1] + a[j])

代码

#include<iostream>#include<cstring>#include<cmath>#include<cstdio>#include<algorithm>#include<stack>#include<queue>using namespace std;const int N = 1000009;int dp[N], a[N], mx[N];int main(){    int n, m;    while(~scanf("%d%d", &m, &n))    {        for(int i=1; i<=n; i++)            scanf("%d", &a[i]);        memset(mx, 0, sizeof(mx));        dp[0] = 0;        int mmax;        for(int i=1; i<=m; i++)        {            mmax = -100000000;            for(int j=i; j<=n; j++)            {                dp[j] = max(dp[j-1]+a[j], mx[j-1]+a[j]);                mx[j-1] = mmax;                mmax = max(mmax, dp[j]);            }        }        printf("%d\n", mmax);    }    return 0;}
0 0