动态规划——最大子段和问题

C++解决最大子段和问题 给定由n个整数(可能为负整数)组成的序列a[1],a[2],a[3],…,a[n],**最大子段和问题**(sum of largest sub-segment problem)要求该序列如a[i]+a[i+1]+…+a[j]的最大值,当所给的整数均为负数时定义子段和为0,依此定义,所求的最优值为:Max{0,a[i]+a[i+1]+…+a[j]},1<=i<=j<=n。例如,当(a[1],a[2],a[3],a[4],a[5],a[6])=(-20,11,-4,13,-5,-2)时,最大子段和为20。 阅读详情
给定n个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。当所给的整均为负数时定义子段和为0,依此定义,所求的最优值为:
  
    Max{0,a[i]+a[i+1]+…+a[j]},1<=i<=j<=n

    例如,当(a1,a2,a3,a4,a4,a6)=(-2,11,-4,13,-5,-2)时,最大子段和为20。


简单算法:

/*
** 简单算法
** 两个for循环,需要O(n^2)的时间
** 空间就存储一个数组,但不是最优
*/
#include<stdio.h>
// besti,bestj记录最大段和时的头尾
// 元素存储在a数组中,a[0]...a[n-1]
int MaxSum(int n, int a[], int &besti, int &bestj) {
	int i , j , k;
	int sum = 0 , thissum;
	// 分别计算以每个元素为起始位置求解最大值
	for(i=0 ; i<n ; i++) {
		thissum = 0;
		// 计算以a[i]为起始元素
		// a[k]为结尾,k从i...n-1,记录下最大值
		for(j=i ; j<n ; j++) {
			thissum += a[j];
			// 当前值如果大于已求最大值,则存储
			if(thissum > sum) {
				sum = thissum;
				besti = i;
				bestj = j;
			}
		}
	}
	return sum;
}

int main() {
	int n , a[100];
	int i , besti , bestj;
	int sum;
	printf("请输入元素的个数:\n");
	scanf("%d",&n);
	printf("请输入各个元素:\n");
	for(i=0 ; i<n ; i++) {
		scanf("%d" , &a[i]);
	}
	 
	sum = MaxSum(n , a , besti , bestj);
	printf("最大字段和为:\n");
	
	for(i=besti ; i<bestj ; i++) {
		printf("%d + " , a[i]);
	}
	printf("%d = %d\n" , a[bestj] , sum);
	return 0;
}



使用分治法: 


如果将给定的序列a[1...n]分成两段长度相近的子段,分别为a[1...n/2] 和 a[n/2+1 ... n] , 试分别求出这两个子段的最大子段和,

则a[1... n]的最大子段和的情形有如下三种:

(1)a[1...n]的最大子段和与a[1...n/2]的最大子段和相同,也就是最大子段和在左半边

(2)a[1...n]的最大子段和与a[n/2+1...n]的最大子段和相同,也就是最大子段和在右半边

(3) a[1...n]的最大子段和跨越两边,和为a[i] + a[i+1] + ... + a[j] , 期中 1<= i <= n/2 ,  n/2+1<= j <= n

其中(1)、(2)两种情形可以用递归求得,而对于第(3)中则可以通过分别计算s1 , s2 

而 s1 为从中间位置a[n/2] 往前加求得最大值

而 s2为从中间位置a[n/2+1]往后加求的最大值

然后 s1 + s2 , 然后比较三种情形下的最大值,求出最大的即为最大子段和


#include<stdio.h>
/*
** 使用分治法
** 时间为O(nlogn)
*/
int MaxSumtwo(int left, int right, int a[]) {
	int sum = 0 , i , j;
	int center , leftsum , rightsum;
	int s1 , s2;
	int lefts , rights;
	// 递归出口
	if(left == right) {
		sum = a[left]>0 ? a[left]:0;
	} else {
		center = (left + right) / 2;
		// 前半段
		leftsum = MaxSumtwo(left,center,a);
		// 后半段
		rightsum = MaxSumtwo(center+1,right,a);
		// 分别计算s1 和 s2
		s1 = 0 ; lefts = 0;
		for(i=center ; i>=left ; i--) {
			lefts += a[i];
			if(lefts > s1) {
				s1 = lefts;
			}
		}

		s2 = 0 ; rights = 0;
		for(j=center+1 ; j<=right ; j++) {
			rights += a[j];
			if(rights >= s2) {
				s2 = rights;
			}
		}
		// 三种情况下的sum值进行比较
		sum = s1 + s2;
		if(leftsum > sum) {
			sum = leftsum;
		}
		if(rightsum > sum) {
			sum = rightsum;
		}
	}
	return sum;
}

int main() {
	int n , a[100];
	int i;
	int sum;
	printf("请输入元素的个数:\n");
	scanf("%d",&n);
	printf("请输入各个元素:\n");
	for(i=0 ; i<n ; i++) {
		scanf("%d" , &a[i]);
	}

	sum = MaxSumtwo(0 , n-1 , a);

	printf("分治法求得的最大子段和为:%d\n" , sum);

	return 0;
}



动态规划算法:

找出数组的最大子段和。(即 max (a[i]+a[i+1]+...+a[j]) 0<=i<=j<=n-1)

现在我们的思路是: 记s[i]为  a[0]到a[i]中包含a[i] (即以a[i]为结尾)的最大子段和,则s[i]如何用s[i-1]来表示?

s[i] = s[i-1] + a[i];  s[i-1]>=0 或者

s[i] = a[i]; s[i-1]<0

所以根据s[i-1]来计算s[i]时会遇到这两种情况。计算s[i]时只用到s[i-1]和a[i], 所以我们可以只保留s[i-1]的值,对于s[i-2]及以前的值可以不保存。

在s[i]中找最大的,就是我们的结果了。

那究竟哪一段是最大的呢。这个方法不唯一。比如,你可以用数组记录每一个s[i],那如果s[i] = a[i]的时候,说明a[i-1]不在s[i]的计算结果中,a[i-1]就没被选择。

现在我们用一个辅助数组P来记录一下, p[i] = 1 表示 在计算s[i]时 包含了 p[i-1]; p[i] = 0 表示 p[i-1]没有被包含。

#include<stdio.h>
/*
** 使用动态规划
** 时间为O(n)
*/
int MaxSumthree(int n , int a[]) {
	int sum , thissum;
	int i;
	sum = 0;
	thissum = 0;
	for(i=0 ; i<n ; i++) {
		thissum += a[i];
		if(thissum < 0 ) {
			thissum = 0;
		}
		if(thissum > sum) {
			sum = thissum;
		}
	}
	return sum;
}

int main() {
	int n , a[100];
	int i;
	int sum;
	printf("请输入元素的个数:\n");
	scanf("%d",&n);
	printf("请输入各个元素:\n");
	for(i=0 ; i<n ; i++) {
		scanf("%d" , &a[i]);
	}

	sum = MaxSumthree(n , a);

	printf("分治法求得的最大子段和为:%d\n" , sum);

	return 0;
}





动态规划求最大子段和 (1)分别用分治法和动态规划法设计最大子段和问题的算法; (2)比较不同算法的时间性能; (3)给出测试数据,写出程序文档。 例:-20,11,-4,13,-5,-2 和 -20, 11, 7, 20, 15, 13 (4)写出实验报告:实验目的、实验内容及步骤、编写的程序(题目,经调试、运行后正确的程序)、编译过程中出现的错误信息、总结讨论本次实验中的问题和收获。 阅读详情

相关推荐

最大子段和问题:蛮力、递归及动态规划

问题描述 求一个序列的最大子段和即最大连续子序列之和。例如序列[4, -3, 5, -2, -1, 2, 6, -2]的最大子段和为11=[4+(-3)+5+(-2)+(-1)+(2)+(6)]。 1. 蛮力算法 思想:从序列首元素开始穷举所有可能的子序列。 代码示例(C++): #include&amp;amp;lt;iostream&amp;amp;gt; using namespace std; int...

SanFancsgo的博客 4万+

最大子段和

问题描述:给定n个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。

Comsmelo的博客 1068

0013算法笔记——【动态规划】最大子段和问题,最大子矩阵和问题,最大m子段和问题

1、最大子段和问题      问题定义:对于给定序列a1,a2,a3……an,寻找它的某个连续子段,使得其和最大。如( -2,11,-4,13,-5,-2 )最大子段是{ 11,-4,13 }其和为20。      (1)枚举法求解      枚举法思路如下:      以a[0]开始: {a[0]}, {a[0],a[1]},{a[0],a[1],a[2]}……{a[0],a[1],

liufeng_king的专栏 3万+

算法设计与分析第二章作业

算法作业

ddhao09的博客 954

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

设数组a长度位n 设b[m]为前m个元素的最大子段和,则b[m]=max{b[m-1]+a[m],a[m]} 即如果b[m-1]>0则b[m]=b[m-1]+a[m] 如果b[m-1]<=0则b[m]=a[m] #include<iostream> using namespace std; int main() { int MaxSum(int *a, int n); ...

qq_37444095的博客 939

动态规划解决最大子段和问题指南

dp从问题定义出发,我们首先需要理解问题的本质,即寻找最大子段和。如果我们能够确定以每个元素结尾的最大子段和,那么全局最大子段和必然是这些局部最大值中的一个。状态转移方程是动态规划的核心,它描述了问题如何从一个状态转换到另一个状态。在此例中,状态转移方程的推导基于以下逻辑:对于数组中的元素arr[i],我们可以选择将其作为新的子段的开始(即arr[i]单独作为一个子段),或者将它加入到前面的最大子段和中(即我们需要比较这两种选择哪一个能给我们更大的和。

weixin_32661831的博客 556

动态规划解最大子段和问题

1 动态规划 1.1 基本思想 动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题。 与分治法的区别在于,适用于动态规划算法求解的问题,经分解得到的子问题往往不是互相独立的;若用分治法求解,则分解得到的子问题数目太多,导致最终解决原问题需指数时间。原因在于:虽然子问题的数目常常只有多项式量级,但在用分治法求解时,有些子问题被重复计算了许多次,如果可以保存已解决的子问题的答案,就可以避免大量重复计算,从而得到多项式时间的算法。 动态规划法的基本思路是:构造一张表来记录所有已解决的子问题的.

qq_39545674的博客 4509

MAX SUM 给定由n整数(可能为负数)组成的序列 {a1,a2,…,an},求该序列形如ai+ai+1,…,+aj的子段和的最大值。当所有的整数均为负数时定义其最大子段和为0。

Description 给定由n整数(可能为负数)组成的序列 {a1,a2,…,an},求该序列形如ai+ai+1,…,+aj的子段和的最大值。当所有的整数均为负数时定义其最大子段和为0。 Input 输入包含多组测试数据。第一行为一个整数C,表示有C组测试数据,接下来有2*C行数据,每组测试数据占2行,每组测试数据第一行是1个整数n,表示有n个整数,接下来一行有n个整数,它们之间用空格隔开. Output 你的输出应该有C行,即每组测试数据的输出占一行,它是计算出的最大子段和. Sample Input 1 6 -2 11 -4 13 -5 -2 Sample Output 20

最大子段和问题(分治法和动态规划)

什么是最大子段和,通俗点讲: 最大子段和就是给了一些数,然后你从中找了几个连续的数,这组连续的数的和比任意一组连续的数的和都大,那么你找的这几个连续的数的和就是这些数的最大子段和。 通俗的听不懂你就看这里: 给定由n个整数(可能为负整数)组成的序列,...,求该序列形如的子段和的最大值。当所有整数均为负整数时定义其最大子段和0。依此定义,所求的最优值为:。例如,当...

qq_41199831的博客 5877

减小伺服电机共振的方法(以松下伺服为例)

嘿 ! 我是【小黄】 , 我们又见面啦 !!! 毕竟技术只有大家交流才会进步嘛 ! 这博客是对自己学习的一点点记录和总结 ,如果您对自动控制感兴趣的话 ,可以关注一下我的动态 , 我们一起学习呀 ! 我们都还年轻 ,我们还有无限可能 。 YES ! 减小伺服电机共振的方法(以松下伺服为例)1. 准备工作:1.1.1 如何推定共振点:1.1.2 测定实操:1.1.3 总结:2. 下期预告: 在我们调试完伺服参数以后机器人运动到某个特定位置会产生振动或异响,我们要做的就是消除这个异响保..

在下小黄的博客 1万+

高通Camera PDAF调试实战:从Type2到Type3的避坑指南与Log分析技巧

本文深入解析高通Camera平台PDAF调试实战,重点对比Type2与Type3的核心差异,提供详细的配置迁移方案和Log分析技巧。针对常见兼容性问题如对焦速度变慢、低光失效等,给出具体解决方案,并分享性能优化案例与高级调试工具链,帮助开发者快速提升PDAF调试效率。

weixin_29164185的博客 408

最大子段和动态规划_动态规划解最大子段和问题

1 动态规划1.1 基本思想动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题。与分治法的区别在于,适用于动态规划算法求解的问题,经分解得到的子问题往往不是互相独立的;若用分治法求解,则分解得到的子问题数目太多,导致最终解决原问题需指数时间。原因在于:虽然子问题的数目常常只有多项式量级,但在用分治法求解时,有些子问题被重复计算了许多次,如果可以保存已解决的子问题的答案...

weixin_39519741的博客 715

意图识别和纠错问题

可想而知,错误的意图识别会带来多大的负面影响。基于词典,就是对用户query内容和词典内容进行比对,比较常见的方式是序列标注问题里用的最大逆向匹配,通过这种方式找到词典里的实体词,匹配触发了自然就有意图了,而在词典匹配的时候,不是使用链表之类的来构造匹配结构,而是使用搜索树的结构,这种匹配的复杂度最低,速度也快,两者结合,其速度甚至比很多模型要快得多(基本上1ms以内就能完成),fasttext速度非常快,但是textcnn之类的其实就已经达到ms级别以上,bert甚至在10ms级别。

TURING.DT 4571

动态规划法求最大子段和问题C++

动态规划法求最大子段和问题 给定由n个整数组成的序列(a1, a2, …, an),求该序列形如(ai, ai+1, ai+2,…, ai+n) 的子段和的最大值,当所有整数均为负整数时,其最大子段和为0。依此定义,所求的最优值为: 动态规划法代码如下: #include <iostream> #include <stdlib.h> using namespace std; int *maxSum(int a[], int b[], int len){

qq_44880708的博客 3546

PCB激光直接成像(LDI)设备技术解析与优化方案

激光直接成像(LDI)是PCB制造中的关键数字化工艺,通过激光束直接在基板上形成电路图案。其核心技术在于高精度光学系统与智能控制算法的结合,工作精度可达微米级。在HDI板、柔性电路等高端PCB制造中,LDI技术能显著提升线宽精度和层间对位准确性。当前行业面临材料适配性、热变形控制等挑战,动态能量补偿、多波长曝光等创新方案正在突破这些瓶颈。随着模块化设计、预测性维护等工程实践的普及,LDI设备综合效率持续提升,为5G、汽车电子等领域的精密电路生产提供关键技术支撑。

weixin_29168393的博客 390

BeckHoff <--> ABB 机器手 Profinet 通讯

本文介绍了BeckHoff PLC与ABB机器人通过PROFINET通信的实现方案。主要内容包括:1)通信接口的详细变量定义,涵盖输入/输出信号、设备状态监控、夹爪控制等关键功能位;2)全局数据结构和变量配置说明;3)机器人任务控制程序的实现方法,包括参数校验、任务指令下发和状态监控机制;4)重点分析了任务调度功能块的代码逻辑,涉及慢速模式处理、多参数配置和执行状态判断。该方案通过结构化变量定义和模块化程序设计,实现了PLC对机器人作业的精确控制,为工业自动化系统集成提供了可靠通信范例。

工控智联驿站 1032

动态规划之最大子段和问题

最大子段和问题1问题定义2 问题分析思路一:穷举法思路二:分治法思路三:动态规划4 核心代码5 例题 1问题定义 2 问题分析 思路一:穷举法 int MaxSum(int n,int a,int &besti,int&bestj) { int sum=0; for(int i=1; i<=n; i++){ int thissum=0; for(int j=i; j<=n; j++){ t

无知的圆的博客 485

手把手教你用分立元件搭建自举电路:解决高端MOS驱动难题

本文详细介绍了如何用分立元件搭建自举电路,解决高端MOS驱动中的栅源极电压不足问题。通过面包板实验,逐步讲解二极管、电容等关键元件的选型与电路搭建,提供波形调试和常见问题排查方法,帮助工程师提升开关电源和电机驱动等应用的效率与可靠性。

weixin_30555125的博客 152

【算法】动态规划:最大子段和问题

#include <iostream> #include <algorithm> using namespace std; //动态规划求解最大子段和问题 int maxSubSumDP(int a[], int n){ int f[n+1]; f[0] = 0; int res = -0x3f3f3f3f; for (int i = 1; i <= n; i++){ if (f[i-1] >= 0){ ...

weixin_44566432的博客 1610

DDR的Controller、Channel、Chip、Rank、Bank、Row、Column、Sided、Dimm

DDR的Controller、Channel、Chip、Bank、Rank、Row、Column、Sided、Dimm

张飞online博客 2万+

Ubuntu 24.04 + RTX 5090 部署 OpenVLA-OFT:从环境配置到机器人任务评估实战

本文详细记录了在Ubuntu 24.04 LTS系统上,为全新RTX 5090显卡配置CUDA 12.8+与PyTorch 2.7.1+开发环境,并成功部署OpenVLA-OFT视觉语言模型进行机器人任务评估的完整实战流程。文章重点解决了驱动安装、依赖版本冲突、路径设置等核心难题,为在最新硬件上运行先进AI机器人模型提供了可靠的避坑指南和性能观察。

n8m7b6v5c4的博客 594

DP动态规划--最大子段和问题

DP–最大子段和问题(动态规划) 问题: 有n个整数组成一个a1,a2,a3,… ,an序列。求其子段和的最大值(子段是连续的) 比如{-2,11,-4,13,-5,-2},最大子段和就是11-4+13=20 解题思路: 这是一个很典型的动态规划性质的题目,我们先设置一个dp数组 dp[i]表示以a[i]为结尾的子段的最大子段和。这里注意一定要以a[i]结尾而不是a[1]到a[i]间任意子段,因为这样有利于利用与维护其最优子结构性质 得到递推式: (1.)dp[i]=dp[i-1]+a[i]---

retr0的博客 1433

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

【动态规划】求最大子段和系列问题

动态规划经典问题:求最大子序列和的题型总结

gzkeylucky的博客 3050

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

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

如果将所给的序列a[1:n]分为长度相等的两段a[1:n/2]和a[n/2:n],分别求出这两段的最大子段和,则a[1:n]的最大子段和有三种情形: 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 (1)(2)可递归求得。对于(3),容易看出a[n/

weiyang_8765的博客 3616

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

上一篇: 动态规划——最长公共子序列问题
下一篇: Eclipse中Server Location 设置
java_wliang
博客等级 码龄15年 19粉丝 82原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值