区间一维dp史上最细总结(听了绝对会了,还不会的一定要进来)

news2024/11/18 18:38:55

目录

那年初夏(三)

引入

1.动态规划是什么?

2.什么是区间动态规划问题? 

定义

性质

3.为何总是要问这种问题?

区间动态规划基本 思考 步骤(划重点)

例题精讲

1.最长上升子序列

题目描述

思路:

代码

2.拦截导弹

题目描述

思路 :

代码

3.护卫队

题目描述

思路 

代码

 4.最大子段和

题目描述

思路 

代码

最后


那年初夏(三)

注:此部分仅为娱乐和引入用,与本文没有太大关联,可以跳过,阅读下面的正文部分。

上篇出现于:DFS(深度优先搜索)详解(概念讲解,图片辅助,例题解释,剪枝技巧)​​​​​​

        孙翱走着,忽然想起,局长听到他一句话后,脸色有些不对劲。“难道……”,这想着,迎面撞上一个人。

        “不好意思”,撞他的是一个年轻的警员,“我正在想如何完成组长布置的 统计犯罪率 最长上升子序列的任务”。

        “哦?你们竟然没有工具,那么原始!我来教你,用动态规划就行,不过涉及到区间动态规划”……

        那位警员,给孙翱点谢金。孙翱拿去买酒,喝完已是深夜。孙翱回到家,酒气冲头,倒头就睡,甚至忘了巡逻……

        四周一下子静了下来。那弯诡异的钩月早已不知不觉的把自己藏进云层里,仿佛在恐惧着什么。惨白的光立即变成了无底的暗。天愈黑了,翻滚着的阴云带着梦魇遮住仅有的一点点光。万物都在随风发抖。

        一人,站于墓前,黑暗之中,喃喃自语;一人,藏于丛中,冷风之中,紧握手枪。

        丛中人,披一黑色衣,紧盯墓前人。

        很久之前,我还远超于他。但,不知怎么的,他突飞猛进,将我甩到身后。我不断努力,想要反超,但总超不过。

         超不过,就模仿他,成为他。

        我不断模仿他,想成为他,但,不可能。学业、事业、爱情,我都不及他。无论怎么模仿,怎么学习,怎么努力。

       模仿不了,就毁灭他,替代他。

        丛中人缓缓举起枪。

        ”砰“,孙翱猛然惊醒,一身冷汗。


引入

        还是那个问题:

1.动态规划是什么?

动态规划(英语:Dynamic programming,简称 DP),是一种在数学、管理科学、计算机科学、经济学和生物信息学中使用的,通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。动态规划常常适用于有重叠子问题和最优子结构性质的问题。

百度的还是那么严谨枯燥,简单来说,动态规划即:
 

通过将问题拆分成一个一个小问题,记录过往结果,减少重复运算。

2.什么是区间动态规划问题? 

定义

区间类动态规划是线性动态规划的扩展,它在分阶段地划分问题时,与阶段中元素出现的顺序和由前一阶段的哪些元素合并而来有很大的关系。

性质

区间 DP 有以下特点:

合并:即将两个或多个部分进行整合,当然也可以反过来;

特征:能将问题分解为能两两合并的形式;

求解:对整个问题设最优值,枚举合并点,将问题分解为左右两个部分,最后合并两个部分的最优值得到原问题的最优值。

3.为何总是要问这种问题?

为何我总是不厌其烦地问这类问题,这种充满概念性的问题?因为,概念是实践的基础。

只有理解了概念,才能完美实践。

动态规划,懂了“通过将问题拆分成一个一个小问题,记录过往结果,减少重复运算。”这句话,就全都会有头绪。重点请看下面的:动态规划基本步骤


区间动态规划基本 思考 步骤(划重点)

这部分,与网上其他的文章都不同,绝对通俗易懂(有点自信)

1.理解题目

2.定义dp[i]或dp[i][j]表示的是什么(通常为 题目要求的东西 的 局部最优解

3.用递归(暴力)的思想分析每一步该怎么做

4.再就递归的思想,确认dp[i]或dp[i][j] 如何得到,由何得到

5.由上得到动态转移方程,并验证

6.思考代码如何实现(考虑细节、输入输出等)


例题精讲

都说,实践出真知,那我们就实践一下。

1.最长上升子序列

题目描述

【题意】

    有n个整数组成的数列,记为: a1、a2、…、an。例如:3,18,7,14,10,12,23,41,16,24。

    如果从中挑出3、18、23、24,并且保留其原有的先后顺序,就是一个长度为4的上升序列;如果挑出3、7、10、12、16、24,,并且保留其原有的先后顺序,则是长度为6的上升序列。

    求出最长的上升序列的长度。

【输入格式】

    第一行一个整数n(1≤n≤1000),下来n个整数。

【输出格式】

    最长上升子序列的长度。

【样例输入】

10

3 18 7 14 10 12 23 41 16 24

【样例输出】

6

思路:

这是一道很经典的一维区间动态规划题。按照我上面的步骤,一步步来做吧!

题目很简洁,不用理解了。

首先,定义dp[i]或dp[i][j]表示的是什么(通常为 题目要求的东西 的 局部最优解)。既然是求一条数字串的最长上升子序列长度,那么其局部最优解就是第i个数的最长上升子序列长度,则a[i]表示包含并第i个数以此为结尾的最长上升子序列长度,因此初始化为1。

然后,用递归(暴力)的思想分析每一步该怎么做。很显然,暴力没什么方法。。。

之后,再就递归的思想,确认dp[i]或dp[i][j] 如何得到,由何得到

对于状态f[i],因为i位置前的每个位置都可能是它上一阶段的状态,所以我们需要从0到i遍历array序列,设遍历到的位置为j,那么:

如果a[i]>a[j],其能做出的决策有:
a[i]加入最长上升子序列
a[i]不加入最长上升子序列:则f[i]=1;
  很显然,能加入一定加入,因为它肯定比不加入好。

如果a[i]<=a[j],其能做出的决策只能是:
a[i]不加入最长上升子序列:则f[i]=1;
————————————————
参考自:
最长上升子序列(LIS)问题的解决及优化_最长上升子序列优化_默归的博客-CSDN博客

在此以后,由上得到动态转移方程,并验证

因为求的是“最长”,因此,用max取大

那么,可得:

(验证就免了。。。) 

最后,思考代码如何实现

第二种情况不会改变f[i],因此就免了。

这里,有一个细节有注意,a[i]表示的是包含并第i个数以此为结尾的最长上升子序列长度,而最长的未必包含最后一个数,因此不能直接输出f[n],而应比较取f[1]-f[n]的最大值,为答案。这个可在循环中完成。

代码

#include<bits/stdc++.h>
using namespace std;
int a[1005],f[1005],m,n,maxx=-1;
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	for(int i=1;i<=n;i++)
	{
		f[i]=1;
		for(int j=i;j>=1;j--)
		{
			if(a[i]>a[j]) f[i]=max(f[i],f[j]+1);
		}
		maxx=max(maxx,f[i]);
	}
	cout<<maxx;//偷懒 
}

2.拦截导弹

题目描述

【题意】
      某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。
      某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
      输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数,导弹数不超过1000),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
【输入格式】
     输入导弹依次飞来的高度。
【输出格式】
     第一行:最多能拦截的导弹数;
     第二行:要拦截所有导弹最少要配备的系统数。
【输入样例】
389 207 155 300 299 170 158 65
【输出样例】
6
2
【来源】Noip1999

思路 :

这道题考的是语文

问题抽象(这里用到了 第一步——理解题目):

1.求最多可以拦截的导弹数,就是求最长递减字串长度
2.求最少的系统数,就是求最长不下降字串的长度。可以这样理解,假设最长的非递减字串长度为n, 那么以这最长的非递减字串的每个字符为分界点,可以将整个串分成n个小递减的小字串,这样每一发炮弹都可以拦截对应的小字串,倘若最长的非递减字串长大于n, 那么势必会有一个小字串不是递减的,则这个字串就要用不止一发子弹才能打下。

好了,理解了题目,后面算法就很简单了,不讲了(不过还要放张图,防止那些“聪明人”)!

 参考:详解拦截导弹问题(动态规划)_Junieson的博客-CSDN博客

代码

#include<bits/stdc++.h>
using namespace std;
int a[1100],fup[1100],fdn[1100],n;
int main()
{
while(scanf("%d",&a[++n])!=EOF);
    fup[0]=0;
    for(int i=1;i<=n;i++)
    {
        fup[i]=1;
        for(int j=i-1;j>=1;j--)
            if(a[i]>a[j])
                fup[i]=max(fup[i],fup[j]+1);
    }
    fdn[n+1]=0;
    for(int i=n;i>=1;i--)
    {
          
        fdn[i]=1;
        for(int j=i+1;j<=n;j++)
            if(a[i]>=a[j])
                fdn[i]=max(fdn[i],fdn[j]+1);
    }
    int s1=0,s2=0;for(int i=1;i<=n;i++) s1=max(s1,fup[i]),s2=max(s2,fdn[i]);
    printf("%d\n%d\n",s2-1,s1);
    return 0;
}

3.护卫队

题目描述

【题意】(本题附有视频)
    护卫车队在一条单行的街道前排成一队,前面河上是一座单行的桥。因为街道是一条单行道,所以任何车辆都不能超车。桥能承受一个给定的最大承载量。为了控制桥上的交通,桥两边各站一个指挥员。护卫车队被分成几个组,每组中的车辆都能同时通过该桥。当一组车队到达了桥的另一端,该端的指挥员就用电话通知另一端的指挥员,这样下一组车队才能开始通过该桥。每辆车的重量是已知的。任何一组车队的重量之和不能超过桥的最大承重量。被分在同一组的每一辆车都以其最快的速度通过该桥。一组车队通过该桥的时间是用该车队中速度最慢的车通过该桥所需的时间来表示的。问题要求计算出全部护卫车队通过该桥所需的最短时间值。
【输入格式】
    第一行包含三个正整数(用空格隔开),第一个整数表示该桥所能承受的最大载重量W(用吨表示);第二个整数表示该桥的长度L(用千米表示);第三个整数表示该护卫队中车辆的总数(n<1000)。接下来的几行中,每行包含两个正整数w和v(用空格隔开),w表示该车的重量(用吨表示,车的重量在int的范围内),v表示该车过桥能达到的最快速度(用千米/小时表示)。车子的重量和速度是按车子排队等候时的顺序给出的。
【输出格式】
    输出一个实数,四舍五入精确到小数点后1位,表示整个护卫车队通过该桥所需的最短时间(用分钟表示)。
【样例输入】
100 5 10
40 25
50 20
50 20
70 10
12 50
9 70
49 30
38 25
27 50
19 70
【样例输出】
75.0

思路 

第一步,理解题目。在去其糟粕(几乎全是糟粕)后,可得出:

1.所有车无论怎么分组,不用考虑排序

 2.任何一组车队的重量之和不能超过桥的最大承重量(边界条件)

 3.一组车队通过该桥的时间是用该车队中速度最慢的车通过该桥所需的时间来表示的

第二步,定义dp[i]或dp[i][j]表示的是什么。f[i]表示1-i辆车通过桥所需的最短时间 

……

后面的以后再搞(注释写得很细,自己看)

代码

#include<bits/stdc++.h>
using namespace std;
double W,L,v[1100],w[1100],zw[1100],f[1100];
//f[i]表示第i辆车通过桥所需的最短时间 
int n;
int main()
{
    scanf("%lf%lf%d",&W,&L,&n); 
    for(int i=1;i<=n;i++)
    {
        scanf("%lf%lf",&w[i],&v[i]);
        v[i]/=60;//因为输出的单位要求是分钟 
        zw[i]=zw[i-1]+w[i];//zw[i]表示从第一辆到第i辆车的总重 
    }
    for(int i=1;i<=n;i++)
    {
        double vm=f[i]=0x3f3f3f3f3f3f3f3f;//因为都应为最小值,因此初始化为最大值 
        for(int j=i;j>=1;j--)
        {
            vm=min(vm,v[j]);//寻找最慢速的车。
            //vm表示车队的速度,因为最慢速的车在车队的时间中唯一有参考价值 
            if(zw[i]-zw[j-1]<=W)//设此车队区间为j~i,若其总重小于等于w,则可行。 
            {
                f[i]=min(f[i],f[j-1]+L/vm); 
                //f[j-1]表示1~j-1辆车的最短时间,l/vm表示分j~i为车队的时间。 
            }
        }
    }
    printf("%.1lf",f[n]);
}

 4.最大子段和

题目描述

【题意】
给定一个n个数ai,求最大子段和:连续一段和S=a[i]+a[i+1]+……+a[j](1<=i<=j<=n),求S的最大值。
【输入格式】
第一行一个整数n( 1<= n <= 10^6)。
下来给出n个整数ai(|ai|<=10^3)。
【输出格式】
一行一个整数,表示最大子段和。
【样例输入】
6
-20 11 -4 13 -5 -2
【样例输出】
20

思路 

设:f[i]表示,包含a[i]并以其为结尾的最大连续和

大于0,就会越来越大;反之,小于即越来越小

那,大于0则加,小于则为a[i]自己。(一重循环,因为是连续的)

同样要注意,a[i]表示的是包含并第i个数以此为结尾的最大字段和,而最长的未必包含最后一个数,因此不能直接输出f[n],而应比较取f[1]-f[n]的最大值,为答案。这个可在循环中完成。

代码

#include<bits/stdc++.h>
using namespace std;
int n,a[1000005],f[1000005],maxx=-10005;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1;i<=n;i++)
    {
        if(f[i-1]>0) f[i]+=a[i]+f[i-1];
        else f[i]=a[i];
        maxx=max(maxx,f[i]);
    }
    printf("%d",maxx);
}

最后

写文章不易,求点赞+评论(骂骂作者也不错)

谢谢!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/185723.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

8个 数据库性能优化方案,你知道几个?(建议收藏)

毫不夸张的说咱们后端工程师&#xff0c;无论在哪家公司&#xff0c;呆在哪个团队&#xff0c;做哪个系统&#xff0c;遇到的第一个让人头疼的问题绝对是数据库性能问题。如果我们有一套成熟的方法论&#xff0c;能让大家快速、准确的去选择出合适的优化方案&#xff0c;我相信…

IB数学AA/AI应该如何选择?

IB数学怎么选课&#xff1f;AA&#xff0c;AI&#xff0c;SL&#xff0c;HL适合哪些学生&#xff1f;如何学习&#xff1f;IB数学&#xff1a;AA与AI&#xff0c;到底应该怎么选&#xff1f;IB数学AA有多难&#xff1f;要不要学数学AA HL&#xff1f;适合学生 IB数学AA AA HL偏…

【SpringCloud复习巩固】Feign

目录 一.HTTP客户端Feign 1.1RestTemplate方式调用存在的问题 1.2Feign的介绍 1.3Feign的使用 1.4自定义Feign的配置 1.4.1配置Feign日志的两种方式 1.5Feign性能优化 1.5.1Feign的性能优化-连接池配置 1.6Feign的最佳实践 一.HTTP客户端Feign 1.1RestTemplate方式调用…

自学软件测试,现在年薪30w,我骄傲了吗?

从小老一辈的人就经常说&#xff0c;小时候不好好读书&#xff0c;长大了只能去工地搬砖。我是从小都不爱读书的人&#xff0c;但在上学时期我一直有一种优越感&#xff0c;认为自己读书很有天赋&#xff0c;读书就是比别人厉害&#xff0c;但事实证明也确实如此&#xff0c;高…

[Android Studio]Android Studio Logcat日志样式设置

&#x1f7e7;&#x1f7e8;&#x1f7e9;&#x1f7e6;&#x1f7ea; Android Debug&#x1f7e7;&#x1f7e8;&#x1f7e9;&#x1f7e6;&#x1f7ea; Topic 发布安卓学习过程中遇到问题解决过程&#xff0c;希望我的解决方案可以对小伙伴们有帮助。 &#x1f4cb;笔记目…

c++IO流!!!开工了!!!

1.什么是IO流 流是若干个字节组成的字节序列&#xff0c;简单来说指的是就是数据从一端到另一端 键盘到程序——>标准输入流程序到屏幕——>标准输出流程序到文件——>文件流 流类体系&#xff1a;一些体系管理输入和输出的流的操作 输入流输出流文件流 ios类 istream…

【DockerCE】使用docker配置和运行HertzBeat

HertzBeat是一款免Agent的监控平台&#xff0c;拥有强大自定义监控能力&#xff0c;可以对应用服务、中间件、数据库、操作系统、云原生等进行监控&#xff0c;配置监控告警阈值&#xff0c;以及告警通知(邮件、微信、钉钉、飞书)。关于这个软件的介绍&#xff0c;我这里就不做…

困扰多年的Docker和iptables的恩怨,今天解决了

先介绍下我的使用环境&#xff1a; 操作系统&#xff1a;CentOS7.9 Docker版本&#xff1a;20.10.21 事情是这样的&#xff0c;安装完Docker的时候&#xff0c;容器镜像都跑起来了&#xff0c;端口也放行了&#xff0c;就是无法控制系统防火墙friewalld,查看firewalld状态报错 …

【微信小游戏开发笔记】第一节:微信小游戏Cocos开发环境配置

微信小游戏开发环境配置 微信小游戏开发前&#xff0c;首先要做一些准备&#xff1a; 注册 微信公众平台 账号&#xff0c;获取小游戏AppID(小程序ID)。安装 微信开发者工具&#xff0c;用于编译小游戏。安装 Visual Studio Code&#xff0c;用于编写游戏逻辑代码。安装并配置…

Linux命令:wget(下载文件)、ssh(登录及免密登录)、scp(远程文件传输)、sh(脚本)

wget 概述 wget是一个下载文件的工具&#xff0c;用在命令行下&#xff0c;下载一些软件或从远程服务器恢复备份到本地服务器 wget支持HTTP&#xff0c;HTTPS和FTP协议&#xff0c;可以使用HTTP代理 支持自动下载 wget可以在用户退出系统的之后在后台执行。意味着你可以登…

C语言选择排序和快速排序(图解过程)+思路清晰

选择排序和快排选择排序时间复杂度和空间复杂度快排&#xff08;三种方式&#xff09;1.hoar时间复杂度和空间复杂度优化--三数取中优化--小区间优化2.挖坑法3.双指针&#xff08;推荐&#xff09;选择排序 本篇文章的重点在快排。因为选择排序无论是在思想上面还是&#xff0…

提供数百万岗位和丰厚利润,苹果却转移产业链,中国制造怎么办?

新年刚过&#xff0c;就传出消息指苹果直接代中国供应链企业向印度提出建厂申请&#xff0c;其中有14家获得了许可&#xff0c;而3家被否决&#xff0c;这凸显出苹果坚定向印度转移生产线&#xff0c;如此做对中国制造将产生深远影响。一、苹果对中国制造的影响巨大苹果为中国提…

新的一年,这份高级测试人的职业素养请收好~

软件测试工程师需要的专业技能计算机领域的专业技能是测试工程师应该必备的一项素质&#xff0c;是做好测试工作的前提条件。尽管没有任何IT背景的人也可以从事测试工作&#xff0c;但是一名要想获得更大发展空间或者持久竞争力的测试工程师&#xff0c;则计算机专业技能是必不…

5G R16+C-V2X赋能下一代智能T-Box,助力智能驾驶时代加速到来

█ 5G技术助力C-V2X持续进化&#xff0c;智能网联新生态逐步建立 汽车行业正面临百年未有之变局&#xff0c;智能汽车已经成为全球汽车产业发展的战略方向。发改委、工信部、交通部等11部委联合印发的《智能汽车创新发展战略》中指出&#xff1a;汽车产业与相关产业全面融合&a…

(二十四)深入理解蓝牙BLE之“H5协议”

前言&#xff1a;蓝牙产品在实际落地中&#xff0c;很多时候采用hostcontroller的通信模型&#xff0c;其中host负责实现协议栈profile是运行在主控cpu上的。controller为另外一颗单独的蓝牙芯片&#xff0c;负责蓝牙link layer的处理&#xff0c;两个芯片通过hci消息来交互数据…

SD卡提示格式化后怎么办?可尝试这种数据恢复方法快速找回!

生活中&#xff0c;虽然我们更习惯用手机、U盘来存储数据&#xff0c;但是对于摄影爱好者&#xff0c;SD卡还是非常刚需。 在使用SD卡存储文件时&#xff0c;经常遇到SD卡无法读取&#xff0c;要求我们格式化后才可以使用。此时&#xff0c;该如何备份里面的数据&#xff0c;或…

IB课程为何号称全球最难国际课程?

在读国际学校的同学们&#xff0c;一定对大名鼎鼎的IB课程不陌生&#xff0c;可是他为什么被称作是它号称最难的国际课程呢&#xff1f;今天就来给大家全面解析一下IB课程&#xff5e; IB课程最开始是IBO为外交官子女开设全球统一标准的课程。IB课程为全球学生开设从幼儿园到大…

【论文速递】TMM2023 - FECANet:用特征增强的上下文感知网络增强小样本语义分割

【论文速递】TMM2023 - FECANet:用特征增强的上下文感知网络增强小样本语义分割 【论文原文】&#xff1a;FECANet: Boosting Few-Shot Semantic Segmentation with Feature-Enhanced Context-Aware Network 获取地址&#xff1a;https://ieeexplore.ieee.org/stamp/stamp.js…

这款小巧精致的 Keychron K7 满足了我对键盘的所有想象

&#x1f53d; 前言 博主是一个“练习”时长两年半的前端码农&#xff0c;在练习期间打交道最多的就是键盘&#xff0c;敲得多了懂得也就多了对键盘的要求也变多了。 之前认为&#xff0c;不就一块键盘嘛&#xff0c;能打字就行。 现在认为&#xff0c;键盘必须要有好的手感&a…

Vue前端基于模板实现word导出功能

目录一、依赖二、模板三、代码一、依赖 // 核心依赖 cnpm i docxtemplater3.32.5 cnpm i file-saver2.0.5 cnpm i jszip-utils0.1.0 cnpm i pizzip3.1.3// ui cnpm i element-ui2.15.8二、模板 public 下新建 test.docx 三、代码 <template><div><el-form …