动态规划(三)——线性dp
一.概念
具有线性阶段划分的动态规划算法叫作线性动态规划(简称线性DP)。若状态包含多个维度,则每个维度都是线性划分的阶段,也属于线性DP,如下图所示:

二.线性dp的三大经典例题
1.LIS问题:求最长上升子序列
给定一个长度为N的数列,求数值严格单调递增的子序列的长度最长是多少。
输入格式
第一行包含整数N。
第二行包含N个整数,表示完整序列。
输出格式
输出一个整数,表示最大长度。
数据范围
1≤N≤1000,
−10&9≤数列中的数≤109
输入样例:
7
3 1 2 1 8 5 6
输出样例:
4
思路:
确定函数为f[i]表示以第i个数结尾的所有子序列集合,f[i]=最大子序列长度;确定状态转移方程:枚举第i个数前面的数j,如果a[j] < a[i]说明a[j]可能是以a[i]为结尾的最长子序列的倒数第二个数,如果是就用f[j]+1更新f[i]。所以状态转移方程为f[i] = max(f[i], f[j]+1)
时间复杂度O(n2)
代码:
#include <bits/stdc++.h>
using namespace std;
const int N=10010;
int n,a[N],f[N];
int main(){
cin>>n;
for(int i=0;i<n;i++) cin>>a[i];
for(int i=0;i<n;i++){
f[i]=1;
for(int j=0;j<i;j++)
if(a[j]<a[i])
f[i]=max(f[i],f[j]+1);
}
int res=0;
for(int i=0;i<n;i++) res=max(res,f[i]);
cout<<res<<endl;
return 0;
}
2.LCS问题:数字三角形

代码:
#include <bits/stdc++.h>
using namespace std;
const int N=510;
const int inf=0x3f3f3f3f;
int n,m;
//f[i][j]表示到达第i行j列这个位置的最大值
int a[N][N],f[N][N];
int main(){
scanf("%d",&n);
//读入三角形数据
for(int i=1;i<=n;i++)
for(int j=1;j<=i;j++)
scanf("%d",&a[i][j]);
//初始化f
for(int i=0; i<=n; i++)
for(int j=0; j<=n; j++)
f[i][j] = -inf;
//线性dp
f[0][0] = 0;
for(int i=1; i<=n; i++)
for(int j=1; j<=i; j++)
f[i][j] = max(f[i-1][j-1], f[i-1][j]) + a[i][j];
int ans = -inf;
for(int i=1; i<=n; i++)
ans = max(ans, f[n][i]);
printf("%d", ans);
return 0;
}
3.LCS问题:最长公共子序列
信息学小组截获了两个序列,序列A和B,规定两个序列所隐藏的信息就是两者的最长公共子串
(注意,这里的子串是指连续的,比如说212325233中212是212325233的子串,而213或者223都不是212325233的子串),
现在,他们将这个任务交给你,你要找出这两个序列所隐藏信息的长度
输入格式
两行,A和B(A、B长度均不大于1000,A、B均由0~9之间的数字组成)
输出格式
一个整数为最长公共子串的长度
样例
样例输入
212325233
312123223
样例输出
5
代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 1000;
char s1[N], s2[N];
int dp[N][N];
int main(){
cin>>s1+1>>s2+1;// 从1开始存储字符串,方便后续的状态转移
int len1=strlen(s1+1);
int len2=strlen(s2+1);
int ans=0;
for(int i=1;i<=len1;i++)
for(int j=1;j<=len2;j++)
if(s1[i]==s2[j]){
dp[i][j]=dp[i-1][j-1]+1;//当前字符相等,最长公共子串长度加1
ans=max(ans,dp[i][j]);
}
else dp[i][j]=0;//当前字符不相等,最长公共子串长度为0
cout<<ans;
return 0;
}
三.典例之拦截导弹
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:
虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。
某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数,导弹数不超过1000),
计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
输入格式
输入只有一行,为若干个正整数,一次为导弹的高度。
输出格式
第一行为最多能拦截的导弹数;
第二行为要拦截所有导弹最少要配备的系统数
样例
样例输入
389 207 155 300 299 170 158 65
样例输出
6
2
核心思想:第一个答案是最长不下降子序列,比较基础,第二个答案是最长上升子序列

y总讲的非常明白哈,这个是基于贪心的思想,贪心得出一堆子序列,最优解也有一堆子序列
只要证明贪心得出的子序列个数与最优解表示的子序列个数一样就行了,证明方式就是A >= B , A <= B,就可以得出 A == B , 显然A >= B , 因为最优解的子序列数量一定是最少的,现在只需要证明A <= B,首先,两个如果不一样的话必定会有不一样的子序列,这对子序列必定会有第一个不相等的数,贪心的策略就是把他接在现有的子序列结尾最小值的后面,所以现在最优解的这个位置的数一定比他大,所以就可以替换掉,所以子序列的个数是不变的,所以又证明了A >= B,所以A == B,现在怎么用代码实现这个贪心的策略,就只需要维护各个子序列的结尾就行了,对于每一个数无非就两种操作,一种是排在某个序列之后,一种是另外再开辟一个序列,而且由于贪心策略的第二条维护的各个子序列的结尾是单调上升的,用这个序列能将所有导弹全部拦截下来,求最小值的话那么就是求最短上升子序列的个数了
#include<bits/stdc++.h>
using namespace std;
const int N = 1010;
int f1[N],f[N],a[N];
int main(){
int n=1,res1=0;
while(scanf("%d",&a[n])!=EOF) n++;
for(int i=1;i<n;i++){
f1[i]=1;
for(int j=1;j<i;j++){
if(a[i]<=a[j]) f1[i]=max(f1[i],f1[j]+1);
}
res1=max(res1,f1[i]);
}
int res2=0;
for(int i=1;i<n;i++){
f1[i]=1;
for(int j=1;j<i;j++){
if(a[i]>a[j]) f1[i]=max(f1[i],f1[j]+1);
}
res2= max(res2,f1[i]);
}
cout<<res1<<"\n"<<res2<<endl;
return 0;
}
如有错误,欢迎大佬们在评论区指正小蒟蒻博主的错误~
#一名爱打篮球的oier#
动态规划(三)——线性dp的更多相关文章
- 动态规划篇——线性DP
动态规划篇--线性DP 本次我们介绍动态规划篇的线性DP,我们会从下面几个角度来介绍: 数字三角形 最长上升子序列I 最长上升子序列II 最长公共子序列 最短编辑距离 数字三角形 我们首先介绍一下题目 ...
- 动态规划_线性dp
https://www.cnblogs.com/31415926535x/p/10415694.html 线性dp是很基础的一种动态规划,,经典题和他的变种有很多,比如两个串的LCS,LIS,最大子序 ...
- 【线性DP】数字三角形
题目链接 原题链接 题目描述 给定一个如下图所示的数字三角形,从顶部出发,在每一结点可以选择移动至其左下方的结点或移动至其右下方的结点,一直走到底层,要求找出一条路径,使路径上的数字的和最大. 7 3 ...
- 动态规划——线性dp
我们在解决一些线性区间上的最优化问题的时候,往往也能够利用到动态规划的思想,这种问题可以叫做线性dp.在这篇文章中,我们将讨论有关线性dp的一些问题. 在有关线性dp问题中,有着几个比较经典而基础的模 ...
- CH5102 Mobile Service【线性dp】
5102 Mobile Service 0x50「动态规划」例题 描述 一个公司有三个移动服务员,最初分别在位置1,2,3处.如果某个位置(用一个整数表示)有一个请求,那么公司必须指派某名员工赶到那个 ...
- 洛谷P1140 相似基因(线性DP)
题目背景 大家都知道,基因可以看作一个碱基对序列.它包含了444种核苷酸,简记作A,C,G,TA,C,G,TA,C,G,T.生物学家正致力于寻找人类基因的功能,以利用于诊断疾病和发明药物. 在一个人类 ...
- 『最长等差数列 线性DP』
最长等差数列(51nod 1055) Description N个不同的正整数,找出由这些数组成的最长的等差数列. 例如:1 3 5 6 8 9 10 12 13 14 等差子数列包括(仅包括两项的不 ...
- 线性DP总结(LIS,LCS,LCIS,最长子段和)
做了一段时间的线性dp的题目是时候做一个总结 线性动态规划无非就是在一个数组上搞嘛, 首先看一个最简单的问题: 一,最长字段和 下面为状态转移方程 for(int i=2;i<=n;i++) { ...
- POJ-2346 Lucky tickets(线性DP)
Lucky tickets Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 3298 Accepted: 2174 Descrip ...
- 2018.08.16 洛谷P2029 跳舞(线性dp)
传送门 简单的线性dp" role="presentation" style="position: relative;">dpdp. 直接推一推 ...
随机推荐
- Java 抽象类的应用:模板方法的设计模式
1 package com.bytezreo.template; 2 3 /** 4 * 5 * @Description 抽象类的应用:模板方法的设计模式 6 * @author Bytezero· ...
- vue 下 placeholder 修改颜色
input::placeholder{ color:#585c89 !important; }
- Python爬虫实战系列3:今日BBNews编程新闻采集
一.分析页面 打开今日BBNews网址 https://news.bicido.com ,下拉选择[编程]栏目 1.1.分析请求 F12打开开发者模式,然后点击Network后点击任意一个请求,Ctr ...
- springMVC之对象中的基本类型数据绑定遇到的问题
最进在开发关于SpringMVC框架的项目时,发现个数据绑定的问题,如果这个实体对象里的字段类型为long.int.double时,客户端就报400语法错误 源代码: controller: @Req ...
- c初探:数据类型、数组、内存布局、指针
c初探:数据类型.数组.内存布局.指针 目录 c初探:数据类型.数组.内存布局.指针 1.基本数据类型 2.格式化 include <stdio.h> 输出控制符 3.数组与内存布局 动态 ...
- 记录--记一次前端CSS升级
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 目前平台前端使用的是原生CSS+BEM命名,在多人协作的模式下,容易出现样式冲突.为了减少这一类的问题,提升研效,我调研了业界上主流的7种 ...
- RMI反序列化分析
RMI介绍 RMI全程Remote Method Invocation (远程方法引用),RMI有客户端和服务端,还有一个注册中心,在java中客户端可以通过RMI调用服务端的方法,流程图如下: 服务 ...
- 启用Windows防火墙后,FTP传输非常慢
我们有一个计划任务,该任务使用Windows命令行FTP程序在两个Windows服务器之间传输大文件(〜130 MB).速度很慢(大约需要30分钟),有时会在传输完成之前终止.服务器是2003年(发送 ...
- verilog注释及vscode插件terosHDL
模型功能 实现代码的注释的方法 基于vscode的文档自动生成 模型框图 `timescale 1ns / 1ps /* */ // ********************************* ...
- Games101--作业2
说明 该作业主要想实现两个三角形的绘制 绘制结果走样 按照课上所讲的方法,对包围盒里面的所有像素进行判断是否在三角形内,然后着色,这样的结果由于采样频率的问题将导致边缘走样现象的发生 if(!insi ...