POJ 2479 Maximum sum

总Time Limit:
1000ms
Memory Limit:
65536kB
Description
Given a set of n integers: A={a1, a2,..., an}, we define a function d(A) as below:
                     t1     t2 
d(A) = max{ ∑ai + ∑aj | 1 <= s1 <= t1 < s2 <= t2 <= n }
i=s1 j=s2

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

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

思路:定义两个数组:left[100000]和right[100000];分别存从左往右,和从右往左的子串的最大值;即:a[0], a[1], a[2],.....a[n],   left[i]表示:在 0 到 n 之间的最大和子串的值;right[i]表示:i到n 之间的最大和子串的值。
      求left[i]的方法与求right[i]的方法类似,这里给求left[i]的方法。采用dp思想:先知道left[0] = a[0] ,定义一个current = a[0],根据current求出a[1]时curent的值,即current在更换值;而current代表以i为一个终点,它(包含它)之前的最大和子串。if (current <0), 那么current = a[i];else current += a[i]。再判断left[i-1]与current的大小,如果前者小,则,left[i] = current;否则,left = left[i-1];
      计算  完left和rihgt后,再得到answer 为 left[i]+right[i+1]里中最大的一个。

以题目给的数据举例:
                    a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9]; 
                    1     -1   2     2     3     -3   4     -4   5     -5  

current(left)     1     0     2     4     7     4     8     4     9     4
left[i]             1     1     2     4     7     7     8     8     9     9

currebt(right)     9     8     9     7     5     2     5     1     5     -5
right[i]           9     9     9     7     5     5     5     5     5     -5




C语言 ac代码
#include

int  a[ 100000];
int  left[ 100000{ 0};        //从左往右时,以这个点为终点,在它前面的子串里面的和最大值;
int  right[ 100000{ 0};        //从右往左时,以这个点为终点,在它前面的子串里面的和最大值;

int  main()
{
    int  T,  n,  i;
    int  current;            
    int      answer;

    scanf( "%d"&T);
    while  (T--)
    {
        scanf( "%d"&n);
        for  (i= 0i
        {
            scanf( "%d"&a[i]);
           
        }

        //计算左边的子串最大值;
        current  left[ 0a[ 0];
        for(i= 1i
        {
            left[i]  left[i- 1];

            if(current  0)
                current  a[i];
            else
                current  current  a[i];

            if(current  left[i- 1])
                left[i]  current;
       
        }

        //计算右边的子串的最大值;
        current  right[n- 1a[n- 1];
        for(i=n- 2i>= 0i--)
        {
            right[i]  right[i+ 1];

            if(current  0)
                current  a[i];
            else
                current  current  a[i];

            if(current  right[i+ 1])
                right[i]  current;
        }

        //找到左右和的最大值;
        answer  left[ 0right[ 1];
        for(i= 1i1;  i++)
        {
            if(answer  (left[i]+right[i+ 1]))
                answer  left[i]+right[i+ 1];
        }
   
        printf( "%d \n "answer);
    }

    return  0;
}










  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值