p1115最大子段和 分治算法题解
题目描述
给出一个长度为n 的序列a,选出其中连续且非空的一段使得这段和最大。
输入格式
第一行是一个整数,表示序列的长度 n。
第二行有 n 个整数,第 i 个整数表示序列的第 i 个数字 a[i]。
输出格式
输出一行一个整数表示答案。
输入输出样例
输入 #1
7
2 -4 3 -1 2 -4 3
7
2 -4 3 -1 2 -4 3
输出 #1
4
4
对于任意一个序列,可以发现最大子序列和只有三种情况:
1.出现在数组的左半部分
2.出现在数组的右半部分
3.出现在数组的中间部分,横跨左右两部分
而且对于左半部分或者右半部分,上述结论也成立,利用这特性,可以写出相应的递归,递归结束的条件是当只有一个元素时,直接返回。
然后求出左边最大值,右边最大值和横跨两边的最大值,返回这三个值中的最大值。
/* P1115 最大子段和 分治算法 */ #include<cstdio> #include<iostream> using namespace std; const int Maxn=200009; int MaxSum(int a[],int left,int right) { if (left==right) return a[left]; else { int mid=(left+right)/2; int leftsum=MaxSum(a,left,mid); int rightsum=MaxSum(a,mid+1,right); int s1; s1=0x80000000; int b=0; for (int i=mid;i>=left;i--) { b=b+a[i]; if (b>s1) s1=b; } int s2=0x80000000; b=0; for (int i=mid+1;i<=right;i++) { b=b+a[i]; if (b>s2) s2=b; } int sum=s1+s2; sum=max(leftsum,sum); sum=max(rightsum,sum); return sum; } } int a[Maxn]; int main() { // freopen("p1115_2.in","r",stdin); int ans; int sum; int n; scanf("%d",&n); ans=sum; for (int i=0;i<n;i++) { scanf("%d",&a[i]); } cout<<MaxSum(a,0,n-1); return 0; }