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
題意:在給出的數列中找到不相交的兩個子段,使其和最大。
分析:動態規劃,dp[i]:=前i個數的最大子段和。在輸入時,正向進行一次dp,求出從左到右的最大子段和,存儲在dp[i]中(不斷累加各數字求子段和sum,sum若小於0則置0,計算各子段sum最大值)。然後再從右向左同樣的方法求出最大字段和,並將字段i~n與字段1~i-1的最大字段和相加,求出最大值。
#include<iostream>
using namespace std;
const int maxn=50005;
const int INF=1e9;
int N,dp[maxn],num[maxn];
int main()
{
int T,sum,Max,ans;
cin>>T;
while(T--)
{
sum=0,Max=-INF;
cin>>N;
for(int i=1;i<=N;i++)
{
scanf("%d",num+i);
sum+=num[i];//子段和
Max=max(sum,Max);//最大子段和
dp[i]=Max;
if(sum<0) sum=0;//當前子段和爲負數,置0
}
sum=0,Max=ans=-INF;
for(int i=N;i>1;i--)
{//求i~N最大子段和
sum+=num[i];
Max=max(sum,Max);
ans=max(dp[i-1]+Max,ans);//與1~i-1內最大子段和相加,求最大值
if(sum<0) sum=0;
}
cout<<ans<<endl;
}
return 0;
}
最大子段積:
考慮存在負數的情況(負負得正),需要分別記錄當前子段內積的最大正數和最小負數
int maxProduct(vector<int>& nums)
{
// write your code here
int posMax = nums[0];
int negMax = nums[0];
int ret = nums[0];
for (int i = 1; i<nums.size(); i++)
{
int tempPosMax = posMax;
int tempNegMax = negMax;
posMax = max(nums[i], max(nums[i] * tempPosMax, nums[i] * tempNegMax));
negMax = min(nums[i], min(nums[i] * tempPosMax, nums[i] * tempNegMax));
ret = max(ret, posMax);
}
if (ret < 0) return -1;
else return ret;
}