HDU 1003 Max Sum * 最长递增子序列(求序列累加最大值)

Max Sum

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 237978    Accepted Submission(s): 56166


Problem Description
Given a sequence a[1],a[2],a[3]......a[n], your job is to calculate the max sum of a sub-sequence. For example, given (6,-1,5,4,-7), the max sum in this sequence is 6 + (-1) + 5 + 4 = 14.
 
Input
The first line of the input contains an integer T(1<=T<=20) which means the number of test cases. Then T lines follow, each line starts with a number N(1<=N<=100000), then N integers followed(all the integers are between -1000 and 1000).
 
Output
For each test case, you should output two lines. The first line is "Case #:", # means the number of the test case. The second line contains three integers, the Max Sum in the sequence, the start position of the sub-sequence, the end position of the sub-sequence. If there are more than one result, output the first one. Output a blank line between two cases.
 
Sample Input
2 5 6 -1 5 4 -7 7 0 6 -1 1 -6 7 -5
 
Sample Output
Case 1: 14 1 4 Case 2: 7 1 6
 
Author
Ignatius.L
 
Recommend
这道题目写的时候WA了很多次
最开始用结构体写的,写了两层循环,然后自己琢磨的瞎改,一直都是两层循环
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<map>
#include<algorithm>
using namespace std;
int a[100010];
struct node
{
    int num1,num2,maxn;
} b[100010];
bool cmp(struct node a,struct node b)
{
    return a.maxn > b.maxn;
}
int main()
{
    int t;
    scanf("%d",&t);
    for(int p=1; p<=t; p++)
    {
        int n;
        scanf("%d",&n);
        for(int i=1; i<=n; i++)
        {
            b[i].num1=0;
            b[i].num2=0;
            b[i].maxn=0;
        }
        for(int i=1; i<=n; i++)
            scanf("%d",&a[i]);
        int j=1;
        for(int k=1; k<=n; k++)
        {
            if(a[k]>=0)
            {
                if(j!=1)
                    j++;
                b[j].maxn += a[k];
                b[j].num1 = k;
                int f = k;
                for(int i=k+1; i<=n; i++)
                {
                    if(a[i]<0)
                    {
                        b[j].num2 = i-1;
                        int d = j;
                        b[++j].maxn = b[d].maxn + a[i];
                        b[j].num1 = f;
                    }
                    if(a[i]>=0)
                    {
                        b[j].maxn += a[i];
                    }
                    if(i==n)
                    {
                        if(a[i]>=0)
                        {
                            b[j].maxn += a[i];
                            b[j].num2 = i;
                        }
                    }
                }
            }
        }
        /*for(int i=1;i<j;i++)
            printf("%d
",b[i].maxn);
        printf("=========
");*/
        sort(b+1,b+j,cmp);
        /*for(int i=1;i<j;i++)
            printf("%d
",b[i].maxn);*/
        printf("Case %d:
",p);
        printf("%d %d %d
",b[1].maxn,b[1].num1,b[1].num2);
        if(p!=t)
            printf("
");
    }
    return 0;
}

后来我师傅指导了我,直接用一层循环就解决了。。

就是用sum不停累加,如果sum小于0了,就重置sum等于当前的a[i],同时更新起始,结束位置

(注意sum最大时有可能为负数,所以定义maxn时要注意maxn取值要为最小--1001 )

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<map>
#include<algorithm>
using namespace std;
int a[100010];
int main()
{
    int t;
    scanf("%d",&t);
    for(int p=1; p<=t; p++)
    {
        int n;
        scanf("%d",&n);
        for(int i=1; i<=n; i++)
            scanf("%d",&a[i]);
        int sum=0,num1=1,tmp=1,num2=1,maxn=-10000000;//注意maxn的取值
        for( int i = 1 ; i <= n ; i++ )
        {
            sum += a[i] ;
            if( sum > maxn )//同时跟新最大值,起始位置,结束位置
            {
                maxn = sum ;
                num2 = i ;
                num1 = tmp ;
            }
            if( sum < 0 )
            {
                sum = 0 ;
                tmp = i + 1 ;
            }
        }
        printf("Case %d:
",p);
        printf("%d %d %d
",maxn,num1,num2);
        if(p!=t)
            printf("
");//还有这个输出要注意!!!最后一组数据不要输出多余空行,其他还要多输出一行空行
    }
    return 0;
}

这段时间学dp学到的dp解法

#include <iostream>
#include<cstdio>
#include<algorithm>
#include<string.h>
using namespace std;
int a[100010],sum[100010],s[100010];
int main(){
    int T;
    cin >> T;
    for(int k=1;k<=T;k++){
        int n;
        cin >> n;
        for(int i=0;i<n;i++){
            cin >> a[i];
        }
        int ans = 0;
        sum[0] = a[0];
        s[0] = 0;
        for(int i=0;i<n;i++){
            if(sum[i-1] >= 0){//只要不是小于零就可以继续加,记下每次加后得到的值  
                sum[i] = sum[i-1] + a[i];
                s[i] = s[i-1];
            }
            else{//小于零重新开始累加 
                sum[i] = a[i];
                s[i] = i;
            }
            if(sum[ans] < sum[i]){//求出记录中的最大值 
                ans = i;
            }
        }
        cout << "Case " << k << ":" << endl;
        cout << sum[ans] << " " << s[ans]+1 << " " << ans + 1 << endl;
        if(k!=T){
            cout << endl;
        }
    }
    return 0;
}
彼时当年少,莫负好时光。
原文地址:https://www.cnblogs.com/l609929321/p/6596196.html