动态规划-最大子段和

1.题目描述在这里插入图片描述
2.算法思想
方法1:枚举
将所有的(i,j)对找出来,计算对应子段和,最后得到最大的。

int MaxSum(int*a ,int *besti,int &bestj){
	int sum=0,T;
	for(int i=1;i<=n;i++)
		for(int j=i;i<=n;j++){
			T=0;
			for(int k=i;k<=j;k++)
				T+=a[j];
			if(T>sum){
			sum=T;*besti=i;*bestj=j;
			}	
		}
}

优化:

int MaxSum(int*a ,int *besti,int &bestj){
	int sum=0,T;
	for(int i=1;i<=n;i++)
		T=0;
		for(int j=i;i<=n;j++){
			T+=a[j];
			if(T>sum){
			sum=T;*besti=i;*bestj=j;
			}	
		}
}

方法二:分治
①划分为左右两半a【1:n/2】 a【n/2+1:n】
②求a【1:n/2】 a【n/2+1:n】的最大子段和
③合并**:计算跨界的子段和**,与a【1:n/2】 a【n/2+1:n】的比较,取最大的。

T(n)=2T(n/2)+O(n)= O(nlogn)

第三种跨界的情况?
i: n/2->1
j: n/2+1->n

int s1=0,lefts=0;
for(int i=mid;i>L;i--){
	lefts+=a[i];
	if(lefts>s1) s1=lefts;
}
int s2=0,rights=0;
for(int i=mid+1;i<R;i++){
	rights+=a[i];
	if(rights>s2) s2=rights;
}

总体:

int MaxSubSum(int *a, int left, int right) {
	int
	sum= 0;
	if (1eft == right)
		sum = a[1eft]>0 ? a[1eft] : 0;
	else {
		int center = (1eft+right)/2;
		int leftsum = MaxSubSum(a, 1eft, center);
		int rightsum = MaxSubSum(a, center+1, right);
		
		int s1=0,lefts=0;
		for(int i=mid;i>L;i--){
			lefts+=a[i];
			if(lefts>s1) s1=lefts;
		}
		int s2=0,rights=0;
		for(int i=mid+1;i<R;i++){
			rights+=a[i];
			if(rights>s2) s2=rights;
		}
		
		sum = 51+s2;
		if (sum < leftsum)
		sum = leftsum;
		if (sum < rightsum)
		sum = rightsum;
	}
	
	return sum;
}

}

方法三:动态规划法
(1)最优子结构
分析:
①( i , j )是和最大的子段,则( i , j ) 是以 j 为右端点的子段中和最大的。
②子问题:以 j ( 1<=j<=n ) 为右端点的最大子段和b[j]。
③原问题 = max { b[1] , b[2], ……b[n] }
(2)状态转移方程:
b[j] = b[j-1]>0? b[j-1]+a[j] : a[j];

int MaxSum(int *a, int n){
	int sum=0,b=0;
	for( int j=1 ; j<=n; j++ ){
		b = b>0 ? b+a[j]:a[j];
		if( b> sum ) b=sum;
	}
	return sum;
}
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hnu哈哈

请接受直女的么么哒????

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值