• POJ 2479 Maximum sum(双向DP)


    Maximum sum
    Time Limit: 1000MS   Memory Limit: 65536K
    Total Submissions: 36100   Accepted: 11213

    Description

    Given a set of n integers: A={a1, a2,..., an}, we define a function d(A) as below:
    Your task is to calculate d(A).

    Input

    The input consists of T(<=30) test cases. The number of test cases (T) is given in the first line of the input. 
    Each test case contains two lines. The first line is an integer n(2<=n<=50000). The second line contains n integers: a1, a2, ..., an. (|ai| <= 10000).There is an empty line after each case.

    Output

    Print exactly one line for each test case. The line should contain the integer d(A).

    Sample Input

    1
    
    10
    1 -1 2 2 3 -3 4 -4 5 -5

    Sample Output

    13

    Hint

    In the sample, we choose {2,2,3,-3,4} and {5}, then we can get the answer. 

    Huge input,scanf is recommended.

    1000ms。50000个数,所以每次处理的时间复杂度不能超过nlogn,否则会超时。所以要让最后扫描一次就能求出答案。

    基本思路就是第一次遍历先定义2个数组,分别记录前i项和(含i)与后n-i+1项和(含i)。
    第二次遍历再定义2个数组。分别记录以i为终点(含i)的最大子段和与以i为起点(含i)的最大子段和。

    第三次遍历再定义2个数组,分别记录第i项(含i)的之前的最大子段和与第i项(含i)的之后的最大子段和。最后遍历一遍数组求出i之前(含i)子段和与i之后(不含i)子段和的最大值就可以。

    #include<stack>
    #include<queue>
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #pragma commment(linker,"/STACK: 102400000 102400000")
    #define lson a,b,l,mid,cur<<1
    #define rson a,b,mid+1,r,cur<<1|1
    using namespace std;
    const double eps=1e-6;
    const int MAXN=50050;
    
    int num[MAXN],n,prev[MAXN],afte[MAXN],ans1[MAXN],ans2[MAXN],fans1[MAXN],fans2[MAXN],sum;
    
    
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
    #endif // ONLINE_JUDGE
        int tcase;
        scanf("%d",&tcase);
        while(tcase--)
        {
            scanf("%d",&n);
            memset(prev,0,sizeof(prev));//前i项和(含i)
            memset(afte,0,sizeof(afte));//后n-i+1项和(含i)
            memset(ans1,0,sizeof(ans1));//以i为终点(含i)的最大子段和
            memset(ans2,0,sizeof(ans2));//以i为起点(含i)的最大子段和
            memset(fans1,0,sizeof(fans1));//第i项(含i)的之前的最大子段和
            memset(fans2,0,sizeof(fans2));//第i项(含i)的之后的最大子段和
            sum=0;
            for(int i=1;i<=n;i++)
            {
                scanf("%d",&num[i]);
                prev[i]=prev[i-1]+num[i];
                sum+=num[i];
            }
            if(n==2)
            {
                printf("%d
    ",sum);
                continue;
            }
            for(int i=n;i>=1;i--)
                afte[i]=afte[i+1]+num[i];
            int minn=0;
            for(int i=0;i<n;i++)
            {
                minn=min(prev[i],minn);
                ans1[i+1]=prev[i+1]-minn;
                //printf("%d
    ",ans1[i+1]);
            }
            minn=0;
            for(int i=n+1;i>0;i--)
            {
                minn=min(afte[i],minn);
                ans2[i-1]=afte[i-1]-minn;
                //printf("%d
    ",ans2[i-1]);
            }
            int maxx=-99999999;
            for(int i=1;i<=n;i++)
            {
                maxx=max(maxx,ans1[i]);
                fans1[i]=maxx;
            }
            maxx=-99999999;
            for(int i=n;i>=1;i--)
            {
                maxx=max(maxx,ans2[i]);
                fans2[i]=maxx;
            }
            int ans=-99999999;
            for(int i=1;i<n;i++)
                ans=max(ans,fans1[i]+fans2[i+1]);//题目规定区间不能有交集
            printf("%d
    ",ans);
        }
        return 0;
    }


  • 相关阅读:
    SoapUI 使用笔记
    git 使用笔记(二)
    git 使用笔记(一)
    jquery 拓展
    hdu 1024 Max Sum Plus Plus (DP)
    hdu 2602 Bone Collector (01背包)
    hdu 1688 Sightseeing (最短路径)
    hdu 3191 How Many Paths Are There (次短路径数)
    hdu 2722 Here We Go(relians) Again (最短路径)
    hdu 1596 find the safest road (最短路径)
  • 原文地址:https://www.cnblogs.com/lxjshuju/p/6819445.html
Copyright © 2020-2023  润新知