动态规划之最大子段和

动态规划——最大子段和 对于含有N个整数的序列{a1,a2,…,an},求函数 𝑓(𝑖, 𝑗)=𝑚𝑎𝑥{0,∑1_(𝑘=𝑖)^𝑗▒𝑎_𝑘 }的最大值 (1≤ i < j ≤ n) 解决上述问题的一个算法描述如下:如果n≤1就直接求解。否则,将序列等分成左、右两个子序列,递归求得两个子序列的最大和S左和S右,以及从中分点分别向左、右两边扫描,找出跨过分界线的最大子列和S中,最后求出Smax=max{ S左, S中,S右}。 阅读详情

最大子段和问题

问题描述如下:

在这里插入图片描述

多重循环求解

问题的核心是求解连续的一段子序列使其和最大。最容易想到的便是通过循环遍历寻找最优的下标i,j使得a[i]+…+a[j]的和最大。很容易看出时间复杂度为O(n^3)。

#include <iostream>
#include<stdlib.h>
#include<stdio.h>
using namespace std;
//最大字段和,暴力破解法,三重循环o(n^3)
int GetSum(int *a,int start,int end)
{
    int ret=0;
    for(int i=start;i<=end;i++)
        ret = ret+a[i];//返回从a[i]到a[j]的和
    if(ret<0) return 0;
    else return ret;
}
int MaxSum(int *a,int n)
{
    int i,j;
    int temp=0;
    for(i=1;i<=n;i++){
        for(j=i;j<=n;j++){
            if(GetSum(a,i,j)>temp)
                temp = GetSum(a,i,j);
                //寻找最优的i和j,可以保存输出
        }
    }
    return temp;

}
int main()
{
    int n;
    cin>>n;
    int *a = new int[n+1];
    for(int i=1;i<=n;i++)
        cin>>a[i];
    cout << MaxSum(a,n);
    return 0;
}
多重循环改进

利用上面两层循环的结果,可以省去GetSum()函数,能充分利用已经得到的结果,避免重复计算,节省了计算时间。时间复杂度为O(n^2)

#include <iostream>
#include<stdlib.h>
#include<stdio.h>
using namespace std;
//核心思想:是找下标i,j使得字段和最大
//暴力破解法就是在不断的遍历寻找最优值
//用两个循环,借助之前的for循环求得sum(a,i,j)再与中间值进行比较
int MaxSum(int *a,int n)
{
    int i,j;
    int temp=0;//定义初值
    for(i=1;i<=n;i++){
        int thisnum = 0;
        for(j=i;j<=n;j++){
            thisnum = thisnum + a[j];
            //进行到这一句thisnum统计的值为a[i]+...a[j],实现了GetSum()函数的功能
            if(thisnum>temp)
                temp = thisnum;
        }
    }
    return temp;

}
int main()
{
    int n;
    cin>>n;
    int *a = new int[n+1];
    for(int i=1;i<=n;i++)
        cin>>a[i];
    cout << MaxSum(a,n);
    return 0;
}
分治算法,分成两半递归

通过分治的思想求最大子段和,将数组分平均分为两个部分,则最大子段和会存在于三种情况下:
1.最大子段和出现在左端
2.最大子段和出现在右端
3.最大子段和横跨在左右段 通过比较大小得到最大子段和
时间复杂度:O(nlogn)
即采用二分法进行二分,然后进行递归求解,分别求出左边连续子段和最大值,右边连续子段和最大值,以及左边和右边连续子段和最大值之和,三者进行比较,从中选择一个最大值进行返回!(这个值即就是当前划分的小区间中最大值)

#include <iostream>
using namespace std;
int MaxSum(int *a,int left,int right)
{
    if(left==right){		//递归出口
        if(a[left]>0) return a[left];
        else return 0;
    }
    int mid=(left+right)/2;
    int leftsum=MaxSum(a,left,mid);//第一种情况,递归左半部分
    int rightsum=MaxSum(a,mid+1,right);//第二种情况,递归右半部分
    //第三种情况,最大字段和是左半部分最大的一部分与右半部分最大的一部分左连续子段和之和。
    int s1=0,s2=0;  
    int temp=0;
    for(int i=mid;i>=left;i--){//从mid开始,逆序计算左边连续最大字段和
        temp = temp+a[i];
        if(temp>s1)  s1=temp;
    }
    temp=0;
    for(int j=mid+1;j<=right;j++){//从mid+1开始,顺序计算右边连续最大子段和
        temp = temp+a[j];
        if(temp>s2) s2=temp;
    }
    int midsum = s1+s2;//这是第三种情况的值
    
    if(midsum<leftsum)  midsum=leftsum;//比较第一种情况和第三种情况,更新最大值
    
    if(midsum<rightsum)  midsum=rightsum;//比较第二种情况的第三种情况,更新最大值
    return midsum;
}
int main()
{
    int n;
    cin>>n;
    int a[n+1];
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    cout<<MaxSum(a,1,n);
    return 0;
}

写出算法时间复杂度的递归表达式,由递归方程可得时间复杂度为O(nlogn)

动态规划算法

运用了动态规划的思想来解决最大子段和问题:
通过遍历累加这个数组元素,定时的更新最大子段和,
如果当前累加数为负数,直接舍弃,重置为0,然后接着遍历累加。

#include <iostream>
using namespace std;
#include<stdio.h>
#include<stdlib.h>
//动态规划算法
int main()
{
    int a[101];
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    int nowsum=0,sum=0;
    //不断更新nowsum,与之同sum比较
    for(int i=1;i<=n;i++){
        //如果上一段累加和为负数,那么起点更新为当前i值,nowsum=a[i]
        if(nowsum<0)  nowsum=a[i];
        //如果为正数,更新nowsum
        else if(nowsum>=0)nowsum=nowsum+a[i];
        //nowsum与sum比较
        if(nowsum>sum)
            sum = nowsum;
    }
    cout<<sum;
    return 0;
}

只有一个for循环,时间复杂度为O(n)。通过上面算法的一步步简化,时间复杂度从O(n^3) 到 O(n^2)再到O(nlogn) 最后降为O(n),充分说明的研究算法的必要性和算法思想的神奇。

在这里插入图片描述

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], 阅读详情

相关推荐

算法设计——最大子段和(动态规划)

问题 给定由n个整数(包含负整数)组成的序列a1,a2,…,an,求该序列子段和的 最大值。当所有整数均为负值时定义其最大子段和为0。 **举个栗子:**当(a1,a2, a3, a4, a5,a6)=(-2,11,-4,13,-5,-2)时,最大子段和为:11-4+13=20 一个简单算法 我们可通过循环来找到最大的和 当字段的开始下标确定后,若 要计算[i:j]的字段和可以利用 上一次计算的...

Doro_的博客 1万+

『动态规划』最大子段和

对所有的对,顺序求和并比较出最大的和 算法改进 动态规划法 b[j]=max(b[j-1]+a[j], a[j]),1

一个专注于客户端开发的技术er,不定期更新Android,Flutter,HormonyOS等方向的使用心得和感悟 7146

动态规划求最大子段和

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

yidao0819的博客 2552

最大子段和(动态规划算法)

最大子段和(动态规划算法) 文章目录最大子段和(动态规划算法)一、思路二、伪代码三、C++代码四、输入实例 一、思路 D[i]表示从i开始的最大字段和。(但我们不是从前往后找字段结束位置) 根据递推公式,我们可知要想求得D[i],就必须知道D[i+1],所以我们从前往后计算。 如下图:以i=12开始的子段和D[12]=X[12]=-1,该子段结束位置Rec[12]=i=12; 当i=11时,D[11+1]<0,所以D[11]=X[11]=7,Rec[i]=i=11; 当i=10时,D[10+1]&g

qq_46036056的博客 1万+

【动态规划】最大子段和

???作者简介:一位喜欢写作,计科专业大二菜鸟一枚 ??个人主页: ??首发日期:2022年5月7日星期六 ??订阅专栏:算法分析与设计 如果文章有帮到你的话记得点赞??+收藏??支持一下哦 ??【动态规划】最大子段和 1??问题引入(恒生电子笔试题) 2??问题描述 3??两种设计方法 穷举法 动态规划法 4??升级版最大字段和 1问题引入(恒生电子笔试题) 输入一个整型数组,数组里有正数也有负数。数组中连续的一个或多个整数组成一个子数组,每个子数组都 有一个和。求所有子数组的和的最.

m0_67402914的博客 886

最大子段和(动态规划)

用动态规划法,C语言编写的解决最大字段和的问题

动态规划---最大子段和,最大子矩阵和,最大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[

Unique-You的博客 1万+

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

最大子段和问题,可参考《算法设计与分析》讲义中关于用动态规划策略求解最大子段和问题的思想设计动态规划算法。本算法用户需要输入元素个数n,及n个整数。程序应该给出良好的用户界面,输出最大子段相关信息,包括:最大字段和、起始下标、终止下标等。 扩展:可以求解数组中任意区间段内的最大子段和及该子段和的起始下标和终止下标。

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

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

qq_41199831的博客 5877

Mac用户解决WPS中的俄语显示红线问题(WPS添加外语拼写检查)

我所使用的WPS版本:AppleStore 下载的 MacOs版 3.3.0 首先,对于 在访达-应用程序中,找到WPS,右键-点击“显示包内容” 然后按照下图的索引目录(Contents\Resource\office6\dicts\spellcheck),最后进入一个叫“spellcheck”的文件夹 最后将下载好的字典包(例如上图中的 en_US就代表美式英语;ru_RU就代表俄语) 关于字典包资源下载,我在网上找到一个Google云盘,里面包含了法语,德语,西语,意大利语,葡萄牙.

qq_48159150的博客 7900

用STM32CubeMX和HAL库,5分钟搞定TB6612驱动直流电机(附完整代码)

本文详细介绍了如何使用STM32CubeMX和HAL库快速配置TB6612驱动直流电机,包括硬件连接、CubeMX工程配置、电机驱动逻辑实现及进阶优化技巧。通过图形化工具和代码示例,即使是新手也能在5分钟内完成电机调速系统的搭建,大幅提升开发效率。

weixin_26854829的博客 266

最大子段和(动态规划详细解析)

给出一个长度为n的序列a,选出其中连续且非空的一段使得这段和最大。

暴力扬 5225

高效数据迁移:ICCAP到ADS的数据导入与导出实战指南

本文提供了从ICCAP到ADS进行高效、准确数据迁移的实战指南。针对射频与微波电路设计中的关键挑战,详细阐述了迁移前的战略规划、ICCAP数据的精细化导出(包括脚本化批处理)、ADS数据的多种导入方法(如Data Items、DML模型库及编程化API),并强调了数据完整性与准确性验证的重要性,确保模型参数和仿真结果在平台间可靠传递。

weixin_29291185的博客 133

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

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

qq_39545674的博客 4509

手把手教你用OpenClaw+飞书打造论文写作AI助手(附踩坑实录)

面对几十篇文献,逐一阅读摘要都费时。我:“请提取桌面‘论文参考文献’文件夹中所有PDF的摘要,整理成表格,包含:论文标题、作者、发表年份、核心方法、主要结论。AI助手:“正在处理...已提取18篇论文摘要,汇总表格已保存到桌面‘文献摘要汇总.xlsx’。这比我自己一个个打开PDF复制粘贴快了不止100倍。OpenClaw+飞书的组合,让AI真正成为了我的“数字员工”。虽然配置过程有些曲折,但看到它在飞书里回应指令、帮我处理繁琐工作时,那种成就感无可替代。如果你也在准备论文,不妨试试这套方案。记住,

AcademicIdeas的博客 1042

Windows游戏多开检测实战:5种技术原理与破解方法详解(附C++代码)

本文深入解析了Windows游戏多开检测的5种核心技术原理,包括进程枚举、互斥体、信号量、窗口及文件映射检测,并详细探讨了对应的破解方法。通过分析这些基于进程和内核对象的攻防机制,为开发者与逆向爱好者提供了从底层理解Windows系统进程管理的实战视角,并附有核心C++代码示例。

weixin_29315091的博客 243

java动态规划求最大子段和_动态规划-最大子段和

2018-01-14 21:14:58一、最大子段和问题问题描述:给定n个整数(可能有负数)组成的序列a1,a2,...,an,求该序列的最大子段和。如果所有整数都是负数,那么定义其最大子段和为0。方法一、最大子段和的简单算法显然可以在O(n^2)的时间复杂度上完成这个问题。但是是否可以对算法进行优化呢?答案是肯定的。方法二、分治算法朴素的分法是二分,问题就是如何merge,在merge的时候,因...

weixin_34055346的博客 1431

Buck电源设计常见的一些问题(四)MOS管振荡抑制方法(二)

另一方面,开关振铃为远超开关频率的高频振铃,并伴随很高的 dV/dt,会带来传导和辐射的 EMI 问题,可能会使得终端产品不能通过 EMI 标准测试,更严重时甚至会干扰开关电源自身的信号电路或临近的其他功能电路的正常工作。选用二极管反向特性好的器件;该电路可等效成图 3 中 LC 谐振电路,新的 LR和 CR为 Lp1、Lp5,Lp3, Lp4, CD等所有参与振铃的寄生感容的复合值。通常 Snubber 的 Csnub取值在数 nF 以上,在振铃频率 fR(加了 snubber 后)下的阻抗很小。

小幽余生不加糖 2893

最大子段和之动态规划法

顺序表应用8:最大子段和之动态规划法 Time Limit: 5 ms Memory Limit: 500 KiB Problem Description 给定n(1&amp;lt;=n&amp;lt;=100000)个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。当所给的整数均为负数时定义子段和为0,依此定义,所求的最优值...

SDUT_OJ 1344

Python爬虫实战:利用Selenium与Playwright抓取美团外卖数据

在当今大数据时代,网络数据采集已成为商业分析和市场研究的重要手段。本文以美团外卖平台为例,详细介绍如何使用Python最新爬虫技术(Selenium、Playwright)进行数据采集,并探讨相关技术原理、反爬应对策略及数据存储方案。通过5000+字的详细讲解和完整代码示例,帮助读者掌握现代网络爬虫开发的核心技能。本文详细介绍了使用Python最新爬虫技术采集美团外卖数据的完整流程,涵盖了从环境配置、页面分析到数据存储的全链路解决方案。

2201_76125261的博客 2550

UG\NX二次开发 找不到指定的dlx文件(Specified Dlx file not found)

有群友问:用Ctrl+U运行的时候就报错,找不到指定的dlx文件Specified Dlx file not found。怎么处理。

王牌飞行员_里海的博客 1131

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

给定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     例如,当(a1,a2,a3,a4,a4,a6)=(-2,11,-4,13,-5,-2)时,最大子段和为20。

执子之手 2021

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

上一篇: 2019年9月CCF CSP 认证题解第一题
下一篇: 分治递归法求数组最大值、数组二分查找
practical_sharp
博客等级 码龄8年 499粉丝 148原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值