Max Sum Plus Plus ,dp,滚动数组

 
                   G - Max Sum Plus Plus
Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u

Description

Now I think you have got an AC in Ignatius.L's "Max Sum" problem. To be a brave ACMer, we always challenge ourselves to more difficult problems. Now you are faced with a more difficult problem.

Given a consecutive number sequence S1, S2, S3, S4 ... Sx, ... Sn (1 ≤ x ≤ n ≤ 1,000,000, -32768 ≤ Sx ≤ 32767). We define a function sum(i, j) = Si + ... + Sj (1 ≤ i ≤ j ≤ n).

Now given an integer m (m > 0), your task is to find m pairs of i and j which make sum(i1, j1) + sum(i2, j2) + sum(i3, j3) + ... + sum(im, jm) maximal (ix ≤ iy ≤ jx or ix ≤ jy ≤ jx is not allowed).

But I`m lazy, I don't want to write a special-judge module, so you don't have to output m pairs of i and j, just output the maximal summation of sum(ix, jx)(1 ≤ x ≤ m) instead. ^_^
 

Input

Each test case will begin with two integers m and n, followed by n integers S1, S2, S3 ... Sn.
Process to the end of file.
 

Output

Output the maximal summation described above in one line.
 

Sample Input

1 3 1 2 3 2 6 -1 4 -2 3 -2 3
 

Sample Output

6 8

Hint

Huge input, scanf and dynamic programming is recommended.
 
求最大m字串和,是杭电1003的加强版,个人感觉难度大多了,光看别人博客就看了好几个小时,才看明白什么意思。写的过程中还是碰到了麻烦,ac不了,最后只能无奈得仿照别人写了一遍。打算等以后能力再强一些的时候再回来看看。
因为n非常大为1000000,所以常规方法肯定不行,采用滚动数组节约内存。状态转移方程为now[j]=max(now[j-1],pre[j-1])+num[j];
其中now记载当前状态,pre记载之前的状态。pre[j]用于求num[j+1]时使用。
对于第j个数,令j一定被选中作为加法中的一个因子,now[j-1]+num[j]表示num[j]与前一个数共同组成一串,pre[j-1]+num[j]表示num[j]另起一串,那么now[j]就能够表示当前的最大值了。整个算法的时间复杂度为O(m*n);
在对now[j+1]做这样的处理后,再更新pre[j]的值。
虽然花了我好几个小时,可是还是感觉只是懵懵懂懂的理解,下面贴两篇代码,前一篇是我没有ac的,后一篇是参考别人的。当然细说起来两篇都是参考的,咱就不深究了哈哈。。。
 
能力还是不行,差远了,只能更努力的去加油,再加油
不过说起来也真弱,第一篇连样例都没过,可是就是想不明白,脑子啊。。。

以下是错误代码:

#include<stdio.h>
#include<string.h>
long num[1000005],pre[1000005],now[1000005];
int max(long a,long b)
{
return a>b?a:b;
}
#define INF 200000000
int main()
{
long m,n,i,j,k,l,s,mm;
while(scanf("%ld%ld",&m,&n)!=EOF)
{
for(i=1;i<=n;i++)
scanf("%ld",&num[i]);
memset(pre,0,sizeof(pre));
memset(now,0,sizeof(now));
for(i=1;i<=m;i++)
{
for(j=i;j<=n;j++)
{
now[j]=max(now[j-1],pre[j-1])+num[j];
pre[j-1]=now[j-1];
}

}
for(i=1,s=0;i<=n;i++)
if(now[i]>s)
s=now[i];
printf("%ld ",s);
}
return 0;
}

以下是正确的:

#include<stdio.h>
#include<string.h>
long num[1000005],pre[1000005],now[1000005];
int max(long a,long b)
{
    return a>b?a:b;
}
#define INF 200000000
int main()
{
    long m,n,i,j,k,l,s,mm;
    while(scanf("%ld%ld",&m,&n)!=EOF)
    {
        for(i=1;i<=n;i++)
            scanf("%ld",&num[i]);
        memset(pre,0,sizeof(pre));
        memset(now,0,sizeof(now));
        for(i=1;i<=m;i++)
        {
            mm=-INF;
            for(j=i;j<=n;j++)
        {
            now[j]=max(now[j-1],pre[j-1])+num[j];
                pre[j-1]=mm;
            if(now[j]>mm)
                mm=now[j];
        }

        }

        printf("%ld
",mm);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/qpddk/p/3251075.html