• 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;
    }
    彼时当年少,莫负好时光。
  • 相关阅读:
    解决了Excel的一个貌似很奇怪的问题~~~
    关闭子页面,刷新父页面
    动态控制DataGrid中的TextBox的状态及输入值!!
    C#对Oracle BLOB字段的写入读取方法
    谈恋爱,好累...
    可移植,可扩展高效Proactor模式
    When are asynchronous file writes not asynchronous...
    [转]How to support 10,000 or more concurrent TCP connections
    [转]Creating a forwarding dll
    [转]非金钱激励员工的108种手段
  • 原文地址:https://www.cnblogs.com/l609929321/p/6596196.html
Copyright © 2020-2023  润新知