標籤:acm
Maximum sum
| Time Limit: 1000MS |
|
Memory Limit: 65536K |
| Total Submissions: 33363 |
|
Accepted: 10330 |
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
1101 -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.
Source
POJ Contest,Author:M[email protected]
解題思路:
題意要求為給定一個數字序列,找出兩段不相交的子段,使這兩個子段的和最大,求出這個最大值。
dp[i]表示 從位置1到i 之間的最大子段和,正向求一遍。然後逆向求最大子段和,比如逆向求出當前位置i的最大欄位和為sum,那麼 ans= max( ans,dp[i-1]+sum), ans即為答案。
代碼:
#include <iostream>#include <stdio.h>#include <string.h>using namespace std;const int maxn=50010;const int inf=-0x7fffffff;int dp[maxn];int num[maxn];int t,n;void DP()//正向求最大子段和{ memset(dp,0,sizeof(dp)); int sum=inf,b=inf; for(int i=1;i<=n;i++) { if(b>0) b+=num[i]; else b=num[i]; if(b>sum) { sum=b; dp[i]=sum; } }}int main(){ scanf("%d",&t); while(t--) { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&num[i]); DP(); int ans=inf,b=0,sum=inf;//逆向求n到i最大欄位和,與正向的最大欄位和相加,求出最大值 for(int i=n;i>1;i--) { if(b>0) b+=num[i]; else b=num[i]; if(b>sum) sum=b; if(sum+dp[i-1]>ans) ans=sum+dp[i-1]; } printf("%d\n",ans); } return 0;}