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;
}
浙公网安备 33010602011771号