p1115最大子段和 分治算法题解

题目描述

给出一个长度为n 的序列a,选出其中连续且非空的一段使得这段和最大。

输入格式

第一行是一个整数,表示序列的长度 n。

第二行有 n 个整数,第 i 个整数表示序列的第 i 个数字 a[i]

输出格式

输出一行一个整数表示答案。

输入输出样例

输入 #1
7
2 -4 3 -1 2 -4 3
输出 #1
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;
}

 

  



 

posted @ 2022-02-28 16:04  心悟&&星际  阅读(79)  评论(0编辑  收藏  举报