DP-循環數組最大子段和


首尾相連數組的最大子數組和

時間限制:1000 ms  |  內存限制:65535 KB
難度:4
描述
給定一個由N個整數元素組成的數組arr,數組中有正數也有負數,這個數組不是一般的數組,其首尾是相連的。數組中一個或多個連續元素可以組成一個子數組,其中存在這樣的子數組arr[i],…arr[n-1],arr[0],…,arr[j],現在請你這個ACM_Lover用一個最高效的方法幫忙找出所有連續子數組和的最大值(如果數組中的元素全部爲負數,則最大和爲0,即一個也沒有選)。
輸入
輸入包含多個測試用例,每個測試用例共有兩行,第一行是一個整數n(1=<n<=100000),表示數組的長度,第二行依次輸入n個整數(整數絕對值不大於1000)。
輸出
對於每個測試用例,請輸出子數組和的最大值。
樣例輸入
6
1 -2 3 5 -1 2
5
6 -1 5 4 -7
樣例輸出
10
14

算法1:

普通的最大子段和,然後依據不同的起點,進行n次最大子段和的計算

時間複雜度過高,無法通過:

優化:

當此次尋找中,如果本組的最大子段和是從ai開始的,那麼下次計算是就從ai開始,而不用從上次的起點相鄰點開始

代碼:

#include <stdio.h>
#include <iostream>
using namespace std;
long long a[100010];
int main()
{
	int n;
	while(cin>>n)
	{
		for(int i = 0; i < n; i++)
		{
			cin>>a[i];
		}
		long long s1 = a[0],s2 = a[0],v1 = 0,v2 = 0,s = 0;
		for(int i = 0; i < n; i++)
		{
			if(v1 <= 0)
				v1 = a[i];
			else
				v1 += a[i];
			s1 = max(s1,v1);
			if(v2 <= 0)
				v2 += a[i];
			else
				v2 = a[i];
			s2 = min(s2,v2);
			s += a[i];
		}
		//printf("%d %d %d\n",s1,s,s2);
		cout<<max(s1,s-s2)<<endl;
	}
	return 0;
}

算法2:

先查找當前順序的最大子段和a

在查找當前順序的最小子段和b

計算數組綜合su

答案就是max(a,su-b)

代碼:

 
#include <stdio.h>
#include <iostream>
using namespace std;
long long a[100010];
int main()
{
	int n;
	while(cin>>n)
	{
		for(int i = 0; i < n; i++)
		{
			cin>>a[i];
		}
		long long s1 = a[0],s2 = a[0],v1 = 0,v2 = 0,s = 0;
		for(int i = 0; i < n; i++)
		{
			if(v1 <= 0)
				v1 = a[i];
			else
				v1 += a[i];
			s1 = max(s1,v1);
			if(v2 <= 0)
				v2 += a[i];
			else
				v2 = a[i];
			s2 = min(s2,v2);
			s += a[i];
		}
		//printf("%d %d %d\n",s1,s,s2);
		cout<<max(s1,s-s2)<<endl;
	}
	return 0;
}
        





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