浅说线性DP(下)

声明

最近博主身体不适,更新较慢,请大家体谅体谅

最大上升子序列

【题目描述】
一个数的序列
你的任务,就是对于给定的序列,求出最大上升子序列和。注意,最长的上升子序列的和不一定是最大的,比如序列(100,1,2,3)的最大上升子序列和为100,而最长上升子序列为(1,2,3)。

【输入】
输入的第一行是序列的长度N(1≤N≤1000)。第二行给出序列中的N个整数,这些整数的取值范围都在0到10000(可能重复)。

【输出】
最大上升子序列和。

如果前面的最长上升子序列那道题理解清楚了,那么该题做起来就会发现本质上和前一道题是一样的。该题的决策对象和阶段都和前一道题一样,只是状态变为dp[i]表示以第i个数作为结尾的最大上升子序列的长度。
决策:这里要求子序列之和最大,对于每一个位置的数,只能从前面的比当前值小的数转移过来,要求序列之和最大,那么这个序列前面选择的数之和要最大,那么我们需要从前面可以选择的点中序列和最大的点转移过来。

我们设dp[i]表示以i结尾的最大子序列之和,那么我们就可以很轻松的得到一下内容
d p [ i ] = m a x ( d p [ i ] , d p [ j ] + a [ i ] ) j ∈ [ 1 , i − 1 ] dp[i]=max(dp[i],dp[j]+a[i]) j\in[1,i-1] dp[i]=max(dp[i],dp[j]+a[i])j[1,i1]
所以就有以下ACcode

#include<bits/stdc++.h>
using namespace std;int a[10010],dp[10010],ans=INT_MIN;
int main(){int n;cin>>n;for (int i=1;i<=n;i++){cin>>a[i];dp[i]=a[i];}	for (int i=1;i<=n;i++){for (int j=1;j<i;j++){if (a[j]<a[i]){dp[i]=max(dp[i],dp[j]+a[i]);}}ans=max(ans,dp[i]);}cout<<ans;return 0;
}

合唱队形

我们先来看一道例题

[NOIP2004 提高组] 合唱队形

题目描述

n n n 位同学站成一排,音乐老师要请其中的 n − k n-k nk 位同学出列,使得剩下的 k k k 位同学排成合唱队形。

合唱队形是指这样的一种队形:设 k k k 位同学从左到右依次编号为 1 , 2 , 1,2, 1,2, , k ,k ,k,他们的身高分别为 t 1 , t 2 , t_1,t_2, t1,t2, , t k ,t_k ,tk,则他们的身高满足 t 1 < ⋯ < t i > t i + 1 > t_1< \cdots <t_i>t_{i+1}> t1<<ti>ti+1> > t k ( 1 ≤ i ≤ k ) >t_k(1\le i\le k) >tk(1ik)

你的任务是,已知所有 n n n 位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。

输入格式

共二行。

第一行是一个整数 n n n 2 ≤ n ≤ 100 2\le n\le100 2n100),表示同学的总数。

第二行有 n n n 个整数,用空格分隔,第 i i i 个整数 t i t_i ti 130 ≤ t i ≤ 230 130\le t_i\le230 130ti230)是第 i i i 位同学的身高(厘米)。

输出格式

一个整数,最少需要几位同学出列。

样例 #1

样例输入 #1

8
186 186 150 200 160 130 197 220

样例输出 #1

4

提示

对于 50 % 50\% 50% 的数据,保证有 n ≤ 20 n \le 20 n20

对于全部的数据,保证有 n ≤ 100 n \le 100 n100

该题实际上就是前面求一个最长上升子序列,对后面求一个最长下降子序列。但是问题在于这两个序列的连接点我们不知道,没有办法直接求解出来,也就是说任意一个点都有可能作为这个连接点,所以我们需要先枚举这个连接点x,再分别对区间[1,x]求最长上升子序列,对区间[x+1,n]求最长下降子序列。这种做法的时间复杂度为O(n3),但是该题的数据范围改为n<=2000,所以还需要优化。

我们先看前面的最长上升子序列,在枚举的连接点i逐渐增大的时候,如果我们已经存储了前i-1个数的最长上升子序列的答案,那么前i个数的最长上升子序列的答案就只有两种情况,第一种就是前面i-1的答案,第二种就是以第i个点作为结尾的答案,没有必要再去前面重新计算一次,每一次的时间复杂度为O(n)。对于后面的下降序列,在i增大时,范围在逐渐缩小,我们只需要把它看做是增大就可以,这种做法在之前做过的一些题中使用过,我们只需要倒着枚举连接点i即可,这样,i在逐渐变小,后面的区间在增大,做法和前面一样。

#include<bits/stdc++.h>
using namespace std;int n,dp1[5000],dp2[5000];//dp1为从前往后的最长上升子序列,dp2为从后往前 
int a[5000],minn=INT_MAX;
int main(){cin>>n;for (int i=1;i<=n;i++){cin>>a[i];dp1[i]=1;dp2[i]=1;}for (int i=1;i<=n;i++){for (int j=1;j<i;j++){if (a[j]<a[i]){dp1[i]=max(dp1[i],dp1[j]+1);}}}for (int i=n;i>=1;i--){for (int j=n;j>i;j--){if (a[i]>a[j]){dp2[i]=max(dp2[i],dp2[j]+1);}}}for (int i=n;i>=1;i--){minn=min(n-dp1[i]-dp2[i],minn);}cout<<minn+1;return 0;
}

最长公共子序列

我们要得到两个字符串的最长公共子序列,暴力做法是先枚举一个字符串的开头,再去枚举另一个字符串的开头,然后找出最大公共子列,时间复杂度为O(n^3)。我们考虑如何优化,前面依然是枚举两个字符串的开头,主要考虑求最大公共子序列时是否可以通过前面算出的答案直接得到正确答案。考虑开头无法知道匹配的最长公共子序列到底匹配到了哪一个位置,所以我们记录下以当前位置结尾的最长公共序列的长度。因为有两个字符串,所以dp[i]无法分别记录两个字符串的结尾位置,所以需要用dp[i][j]。

状态:我们设dp[i][j]表示前缀长度为i的a子串和一个长度为j的b序列的最长公共子序列的长度。决策对象:每个位置的字符。阶段:a串的每个位置和b串的每个位置都可以组合,一共有n*m个阶段。决策:如果a[i]==b[j],那么(i,j)相对于(i1,j-1)会多匹配一个,即dp[i][j]=dp[i-1][j-1]。如果a[i]!=b[j],答案就是dp[i-1][j-1]吗?其实并不是,因为a[i]可以和b[j-1]匹配,或者b[j]可以和a[i-1]匹配,这种情况下,dp[i-1][j-1]的答案是错误的。

当a[i]!=b[j]时,正确答案是dp[i][j]=max (dp[i-1][j],dp[i][j-1]),那么万一是a[i]和b[j1]、a[i-1]和b[j]都无法匹配的情况,是否还需要和dp[i-1][j-1]比较呢?不需要,因为在这种情况下,计算dp[i][j-1]时,a[i]!=b[j-1],那么dp[i][j-1]=max(dp[i-1][j-1], dp[i][j-2]),这个答案中已经报了dp[i-1][j-1]的情况,所以不需要再和dp[i-1][j-1]比较。还需要设置初始值,当a串和b串都没有字符时,最长公共串长度为1,即dp[0][0]=0。

#include<bits/stdc++.h>
using namespace std;int dp[1010][1010];
int main(){string a,b;cin>>a>>b;dp[0][0]=0;for (int i=1;i<=a.length();i++){for (int j=1;j<=b.length();j++){if (a[i-1]==b[j-1]) dp[i][j]=dp[i-1][j-1]+1;else dp[i][j]=max(dp[i-1][j],dp[i][j-1]);}}cout<<dp[a.length()][b.length()];return 0;
}

最长公共子串

该题和上一题的状态、对象、阶段都是相同的,不同的是状态的转移。dp[i][j]表示以位置i结尾的a串和以位置j结尾的b串的最长公共子串. 如果a[i]!=b[j],那么这个子串一定是不可以匹配的,因为这里说了分别以i,j结尾,所以dp[i][j]=0。如果a[i]=b[j],长度就在之前的dp[i-1][j-1]的基础上增加1,即dp[i][j]=dp[i-1][j-1]+1。

#include<bits/stdc++.h>
using namespace std;int dp[1500][1510];
int maxn=INT_MIN;
int main(){string a,b;cin>>a>>b;dp[0][0]=0;for (int i=1;i<=a.length();i++){for (int j=1;j<=b.length();j++){if (a[i-1]==b[j-1]){dp[i][j]=dp[i-1][j-1]+1;}maxn=max(dp[i][j],maxn);}}cout<<maxn;return 0;
}

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

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

相关文章

03-3.3.1 栈在括号匹配中的应用

&#x1f44b; Hi, I’m Beast Cheng&#x1f440; I’m interested in photography, hiking, landscape…&#x1f331; I’m currently learning python, javascript, kotlin…&#x1f4eb; How to reach me --> 458290771qq.com 喜欢《数据结构》部分笔记的小伙伴可以订…

echarts的使用

一 echarts的使用 引入 echarts.js 文件 <script src"https://cdn.jsdelivr.net/npm/echarts/dist/echarts.min.js"></script> 准备一个呈现图表的盒子 <div class"container"><div class"t_header"><span>端午…

东方博宜1760 - 整理抽屉

题目描述 期末考试即将来临&#xff0c;小T由于同时肩负了学习、竞赛、班团活动等多方面的任务&#xff0c;一直没有时间好好整理他的课桌抽屉&#xff0c;为了更好地复习&#xff0c;小T首先要把课桌抽屉里的书分类整理好。 小T的抽屉里堆着 N 本书&#xff0c;每本书的封面上…

智能视频监控平台LntonCVS视频融合共享平台保障露营安全解决方案

在当今社会&#xff0c;都市生活的快节奏和压力使得越来越多的人渴望逃离城市的喧嚣&#xff0c;寻求一种短暂的慢生活体验。他们向往在壮丽的山河之间或宁静的乡村中露营&#xff0c;享受大自然的宁静与美好。随着露营活动的普及&#xff0c;露营地的场景也变得更加丰富多样&a…

使用python绘制核密度估计图

使用python绘制核密度估计图 核密度估计图介绍效果代码 核密度估计图介绍 核密度估计&#xff08;Kernel Density Estimation&#xff0c;KDE&#xff09;是一种用于估计数据概率密度函数的非参数方法。与直方图不同&#xff0c;KDE 可以生成平滑的密度曲线&#xff0c;更好地…

Mybatis使用缓存的配置总结

1.全局变量配置cacheEnabled&#xff1a; ture&#xff08;默认&#xff09;&#xff1a;开启二级缓存&#xff0c; false&#xff1a;关闭二级缓存&#xff0c;但一级缓存不受影响 2.映射文件中mapper标签下&#xff1a; 配置有&#xff1a;开启二级缓存 没配置有&#x…

LeetCode62不同路径

题目描述 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#xff09;。问总共有多少条不同的路径&#xff1f; …

大模型参加高考,同写2024年高考作文,及格分(通义千问、Kimi、智谱清言、Gemini Advanced、Claude-3-Sonnet、GPT-4o)

大家好&#xff0c;我是章北海 今天高考&#xff0c;上午的语文结束&#xff0c;市面上又要来一场大模型参考的文章了。 我也凑凑热闹&#xff0c;让通义千问、Kimi、智谱清言一起来写一下高考作文。 公平起见&#xff0c;不加任何其他prompt&#xff0c;直接把题目甩过去。…

网络基础_02

1.ARP协议 地址解析协议&#xff08;Address Resolution Protocol&#xff09; 已知对方的三层ip地址&#xff0c;需要二层mac地址 当一台设备&#xff08;请求方&#xff09;需要知道某个 IP 地址对应的 MAC 地址时&#xff0c;会使用 ARP封装一个数据帧。这台设备的网络层以…

华为RH2288H V3服务器iBMC的SSL证书续期

本文对华为RH2288H V3服务器iBMC的SSL证书续期&#xff0c;以避名登录告警提示及主机状态异常。 一、检查现网服务器iBMC的SSL证书到期时间 登录iBMC&#xff0c;点击配置--SSL证书&#xff0c;如下&#xff1a; 可以看到本服务器SSL证书将于今年7月22日到期。 二、联系厂家…

【第四节】C/C++数据结构之树与二叉树

目录 一、基本概念与术语 二、树的ADT 三、二叉树的定义和术语 四、平衡二叉树 4.1 解释 4.2 相关经典操作 4.3 代码展示 一、基本概念与术语 树(Tree)是由一个或多个结点组成的有限集合T。其中: 1 有一个特定的结点&#xff0c;称为该树的根(root)结点&#xff1b; 2 …

【Linux】进程2——管理概念,进程概念

1.什么是管理&#xff1f; 那在还没有学习进程之前&#xff0c;就问大家&#xff0c;操作系统是怎么管理进行进程管理的呢&#xff1f; 很简单&#xff0c;先把进程描述起来&#xff0c;再把进程组织起来&#xff01; 我们拿大学为例子 最典型的管理者——校长最典型的被管理…

来自工业界的知识库 RAG 服务(三),FinGLM 竞赛获奖项目详解

背景介绍 前面介绍过工业界的 RAG 服务 QAnything 和 RagFlow 的详细设计&#xff0c;也介绍过来自学术界的 一些优化手段。 前一阵子刚好看到智谱组织的一个金融大模型比赛 FinGLM&#xff0c;主要做就是 RAG 服务的竞赛&#xff0c;深入研究了其中的几个获奖作品&#xff…

Pyramid Vision Transformer, PVT(ICCV 2021)原理与代码解读

paper&#xff1a;Pyramid Vision Transformer: A Versatile Backbone for Dense Prediction without Convolutions official implementation&#xff1a;GitHub - whai362/PVT: Official implementation of PVT series 存在的问题 现有的 Vision Transformer (ViT) 主要设计…

C++结合ffmpeg获取声音的分贝值

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、分贝是什么&#xff1f;1.功率量2.场量 二、实际操作1.分析wav文件2.读取麦克风 总结 前言 最近面对一个需求&#xff0c;就是需要传递声音文件到模型里推…

链表的回文结构OJ

链表的回文结构_牛客题霸_牛客网对于一个链表&#xff0c;请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法&#xff0c;判断其是否为。题目来自【牛客题霸】https://www.nowcoder.com/practice/d281619e4b3e4a60a2cc66ea32855bfa?tpId49&&tqId29370&rp1&a…

CodeMeter助力Hilscher,推动实现全球智能制造连接解决方案

Hilscher的旗舰店为开放工业4.0联盟&#xff08;OI4&#xff09;社区提供了应用商店的便捷和开放性&#xff0c;将这一概念引入工业领域。该商店依托CodeMeter的许可证管理和加密保护&#xff0c;为工业用户提供了丰富的应用和解决方案库&#xff0c;满足他们在车间自动化和连接…

2020年06月C语言二级真题

计算矩阵边缘元素之和 题目描述 输入一个整数矩阵&#xff0c;计算位于矩阵边缘的元素之和。 所谓矩阵边缘的元素&#xff0c;就是第一行和最后一行的元素以及第一列和最后一列的元素。 输入格式 第一行分别为矩阵的行数n和列数m&#xff0c;两者之间以一个空格分开。 接下来输…

WPF中读取Excel文件的内容

演示效果 实现方案 1.首先导入需要的Dll(这部分可能需要你自己搜一下) Epplus.dll Excel.dll ICSharpCode.SharpZipLib.dll 2.在你的解决方案的的依赖项->添加引用->浏览->选择1中的这几个Dll点击确定。(添加依赖) 3.然后看代码内容 附上源码 using Excel; usi…

计网复习资料

一、选择题&#xff08;每题2分&#xff0c;共40分&#xff09; 1. Internet 网络本质上属于&#xff08; &#xff09;网络。 A.电路交换 B.报文交换 C.分组交换 D.虚电路 2.在 OSI 参考模型中,自下而上第一个提供端到端服务的是( )。 A.数据链路层 B.传输…