题目:
N个整数组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的连续子段和的最大值。当所给的整数均为负数时和为0。
例如:-2,11,-4,13,-5,-2,和最大的子段为:11,-4,13。和为20
分治法:
#include"stdio.h"
#include"stdlib.h"
#include"string.h"
#include"algorithm"
#include"math.h"
using namespace std;
//求最大连续和
//时间复杂度 O(nlogn)
long long maxsum(int a[],int x,int y) //返回闭合区间【x,y】中最大的连续和
{
if(x==y) return a[x]; //只有一个元素直接返回
//int m=(x+y)/2;
int m=x+(y-x)/2;
//相比上一句,这样写更具有鲁棒性。
//分治的第一步,划分成【x,m】和【m+1,y】 两部分
long long sum_max=max(maxsum(a,x,m),maxsum(a,m+1,y));
//分治法的第二步,递归求解(子问题的最优解)
long long L_sum=0,R_sum=0,tem=0;
for(int i=m;i>=x;i--)
L_sum=max(L_sum,tem+=a[i]);
//分治法第三步(1),从分界点开始往左的最大连续和L
tem=0;
for(int i=m+1;i<=y;i++)
R_sum=max(R_sum,tem+=a[i]);
//分治法第三步(1),从分界点开始往右的最大连续和R
return max(sum_max,L_sum+R_sum);
//把子问题的解与 (L和R的和) 比较
}
int main()
{
int n,*a;
scanf("%d",&n);
a=(int *)malloc(sizeof(int)*n);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
printf("%lld\n",maxsum(a,0,n-1));
return 0;
}
dp:
//转移方程dp[i]=max(dp[i-1]+a[i],a[i])
#include"stdio.h"
#include"stdlib.h"
#include"algorithm"
#define N 50003
int a[N]={0};
int c[N]={0};
long long MaxSum()
{
int i,n;
long long b=0,sum=0;
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
for(i=0;i<n;i++)
{
if(b>0) //直到累加和小于0
b+=a[i];
else
b=a[i];
if(b>sum)
sum=b;
}
return sum;
}
int main()
{
printf("%lld\n",MaxSum());
}
可以继续学习有光最大字段和相关问题: