HDU 1024 Max Sum Plus Plus 简单DP

这题的意思就是取m个连续的区间,使它们的和最大,下面就是建立状态转移方程

dp[i][j]表示已经有 i 个区间,最后一个区间的末尾是a[j]   

那么dp[i][j]=max(dp[i][j-1]+a[j],max(dp[i-1][1..j-1])+a[j])

看数据范围,1e6 肯定开不下数组,观察发现,dp[i][j]仅和dp[i][j-1]和dp[i-1][1..j-1]中最大值有关,即只和dp[i-1]有关

所以开滚动数组求解   复杂度可以通过开数组mmax[j]表示dp[i-1][1..j-1]中最大值,这个数组可以同时更新,这样复杂度降到O(mn)

然后,我觉得肯定是m比较小,要不然肯定也是超时啊QAQ......

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include <algorithm>
#include<cstring>
using namespace std;
const int maxn=1000005;
const int INF=0x7fffffff;
typedef long long sum[maxn];
int a[maxn],dp[maxn],mmax[maxn];
int main()
{
    int n,m;
    while(~scanf("%d%d",&m,&n))
    {
        for(int i=1; i<=n; ++i)
            scanf("%d",&a[i]);
        int ans=-INF;
        memset(mmax,0,sizeof(mmax));
        for(int i=1; i<=m; ++i)
        {
            int cc=-INF;
            ans=-INF;
            for(int j=i; j<=n; ++j)
            {
                dp[j]=max(dp[j-1]+a[j],mmax[j-1]+a[j]);
                mmax[j-1]=cc;
                cc=max(cc,dp[j]);
            }
            ans=max(ans,cc);
        }
        printf("%d
",ans);
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/shuguangzw/p/4993256.html