http://poj.org/problem?id=2479
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.
题意分析:
找出两个不重合的区间,使区间中的值相加最大。
解题思路:
dp1[i] 代表从 1 到 i 区间中能取到的最大值, dp2[i] 代表从 i 到 n 区间中能取到的最大值,那么
dp1[ i ] + dp2[ i + 1 ] 代表,前一区间是1到 i, 后一区间是i+1 到n,能取到的最大值,
再遍历i找出最大的值。
#include <stdio.h>
#include <algorithm>
#define N 50050
using namespace std;
int a[N], dp1[N], dp2[N], sum, ans;
int main()
{
int T, n, i, count, min1, min2;
scanf("%d", &T);
while(T--)
{
scanf("%d", &n);
count=0;
min1=min2=-99999999;
for(i=1; i<=n; i++)
{
scanf("%d", &a[i]);
if(a[i]>=0)
count++;
else{
if(a[i]>min1)
{
min2=min1;
min1=a[i];
}
else if(a[i]>min2)
min2=a[i];
}
}
if(count==0)
{
printf("%d
", min1+min2);
continue;
}
sum=0;
for(i=1; i<=n; i++)
{
sum+=a[i];
if(sum<0)
sum=0;
dp1[i]=max(dp1[i-1], sum);
}
dp2[n+1]=0;
sum=0;
for(i=n; i>0; i--)
{
sum+=a[i];
if(sum<0)
sum=0;
dp2[i]=max(dp2[i+1], sum);
}
ans=0;
for(i=1; i<=n; i++)
{
// printf("%d %d
", dp1[i], dp2[i+1]);
ans=max(ans, dp1[i]+dp2[i+1]);
}
if(count==1)
printf("%d
", ans+min1);
else
printf("%d
", ans);
}
return 0;
}