[HDU 1024] Max Sum Plus Plus (DP)

HDU - 1024
定义 dp[i][j] 为取第 i 个数的情况下,前 i 个数组成 j 组 得到的最大和
转移方程为 dp[i][j] = max(dp[i-1][j], max(dp[0..i-1][j-1]) ) + inpt[i]
意思是:考虑第 i 个数,要么把它和第 i-1 个数放到一组 (dp[i-1][j]), 要么另起一组,从0..i-1中转移 (max(dp[0..i-1][j-1]))
时间 O(n^2) 空间 O(n*m)
这题需要滚动数组,把第二维滚动掉,同时可以发现,从 dp[0..i-1][j-1] 中转移只需记录前 i-1 个的最大值即可
优化后时间 O(n) 空间 O(n)
for j=1..m :
for i=j+1..n :
dp[i] 表示前 i 个数组成 j 组的最大和,premax[i] 表示前 i 个数组成 j-1 组的最大和的最大值
转移方程为 dp[i] = max(dp[i-1], premax[i-1]) + inpt[i]
然后边做边更新 premax[i]

#if _WIN32||_WIN64
#define lld I64d
#define llu I64u
#endif
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
using namespace std;
#define MST(a,b) memset(a,b,sizeof(a))
#define CLR(a) MST(a,0)
#define LL long long
#define ULL unsigned long long
int maxx(int a,int b){return a>b?a:b;}
int minn(int a,int b){return a<b?a:b;}
int abss(int a){return a<0?(-a):a;}

const int maxn=1e6+10,INF=1e9;
int N,M;
int inpt[maxn];
int dp[maxn];
int premax[maxn];

int main()
{
    while(~scanf("%d%d", &M, &N))
    {
        CLR(dp);
        CLR(premax);
        int ans;
        for(int i=1; i<=N; i++) scanf("%d", &inpt[i]);
        for(int j=1; j<=M; j++)
        {
            dp[j]=dp[j-1]+inpt[j]; // 要组成 j 组,至少要有 j 个数
            ans=dp[j];
            for(int i=j+1; i<=N; i++) 
            {
                dp[i]=maxx(dp[i-1],premax[i-1])+inpt[i];
                premax[i-1]=ans; // 更新 premax
                ans=maxx(ans,dp[i]);
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}

你可能感兴趣的:(dp)