POJ 2479 Maximum sum 動態規劃 最大子段和 最大子段積

 

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

 

題意:在給出的數列中找到不相交的兩個子段,使其和最大。

分析:動態規劃,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;
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章