POJ 2479 Maximum sum

来源:互联网 发布:关于淘宝美工工作流程 编辑:程序博客网 时间:2024/06/13 08:13
总Time Limit:
1000ms
Memory Limit:
65536kB
Description
Given a set of n integers: A={a1, a2,..., an}, we define afunction 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 testcases (T) is given in the first line of the input.
Each test case contains two lines. The first line is an integern(2<=n<=50000). The second line contains n integers: a1, a2,..., an. (|ai| <= 10000).There is an empty line after eachcase.
Output
Print exactly one line for each test case. The line shouldcontain 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 getthe 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      3   -3   4   -4   5   -5  

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

currebt(right)      8   9      5   2      1   5    -5
right[i]           9   9      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
原创粉丝点击