[HDU 1024] Max Sum Plus Plus (DP)

来源:互联网 发布:黑魔棒淘宝 编辑:程序博客网 时间:2024/06/18 10:12

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 longint 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;}
0 0