最大子段和问题的分治算法和动态规划算法

如果将所给的序列a[1:n]分为长度相等的两段a[1:n/2]和a[n/2:n],分别求出这两段的最大子段和,则a[1:n]的最大子段和有三种情形:(当所有整数均为负数时定义其最大子段和为0)

1)a[1:n]的最大子段和与a[1:n/2]的最大子段和相同;

2)a[1:n]的最大子段和与a[n/2:n]的最大子段和相同;

3)a[1:n]的最大子段和为Σ(k=i~j)ak,且1<=i<=n/2,n/2+1<=j<=n;

(1)(2)可递归求得。对于(3),容易看出a[n/2]与a[n/2+1]在最优子序列中。据此可以设计出分治算法如下:

#include
using namespace std;

int MaxSubSum(int *a,int left,int right)
{
	int i,leftsum,rightsum,lefts,rights,center,s1,s2;
	int sum=0;

	if(left==right)
		sum=a[left]>0?a[left]:0;
	else
	{
		 center=(left+right)/2;
		 leftsum=MaxSubSum(a,left,center);
		 rightsum=MaxSubSum(a,center+1,right);

		 s1=0;
		 lefts=0;
		for(i=center;i>=left;i--)
		{
			lefts+=a[i];
			if(lefts>s1)
				s1=lefts;
		}

		 s2=0;
		 rights=0;
		for(i=center+1;i<=right;i++)
		{
			rights+=a[i];
			if(rights>s2)
				s2=rights;
		}

		sum=s1+s2;
		if(sum
//结果20






设b[j]为序列a[k]从i~j的各子段和中的最大值(1<=j<=n)。有b[j-1]>0时,b[j]=b[j-1]+a[j],否则b[j]=a[j]。

所以b[j]的动态规划式为:b[j]=max{b[j-1]+a[j],a[j]}   (1<=j<=n)

#include
using namespace std;

int MaxSum(int n,int *a)
{
	int sum=0,b=0;
	for(int i=0;i<=n;i++)
	{
		if(b>0)
			b+=a[i];
		else
			b=a[i];
		if(b>sum)
			sum=b;
	}
	return sum;
}


int main()
{
	int a[6]={-2,11,-4,13,-5,-2};
	int s;

	s=MaxSum(5,a);
	cout<



你可能感兴趣的:(算法初步)