51Nod 1049 最大子段和(分治/dp)

题目:

       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());
}

可以继续学习有光最大字段和相关问题:
          

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值