当前位置: 首页 > news >正文

线性DP:最长上升子序列(子序列可不连续,子数组必须连续)

 

目录

 

Q1:简单遍历

Q2:变式(加大数据量)


Q1:简单遍历

Dp问题

状态表示

f(i,j)

集合所有以第i个数结尾的上升子序列集合
-
f(i,j)的值存的是什么序列长度最大值max
-

状态计算

(其实质是集合的划分)

划分

f[ i ] = max(f[ i ] , f [ j ]+1), j < i ,a[ j ]<a[ i ]


以上面的条件作为选或不选聚类形成划分依据

#include<iostream>
#include<algorithm>
using namespace std;const int N=1010;int n;
int a[N], f[N];int main()
{cin>>n;for (int i = 1; i <= n; i++) cin>>a[i];for (int i = 1; i <= n; i++){f[i] = 1;  //初始化,只有a[i]一个数for (int j = 1; j < i; j++)//j<i,a[j] < a[i],max三个条件作为集合划分为选或不选的依据if (a[j] < a[i])f[i] = max(f[i], f[j] + 1);}int res = 0;for (int i = 1; i <= n; i++) res = max(res, f[i]);//在dp数组内找maxcout<<res;return 0;
}


Q2:变式(加大数据量)

最终的逻辑上的候选最长子序列中越靠前的数字越小越好

 比如说3 8和1 8,1 8组合更好, 因为1和8之间的差距大,可以插入作为序列长度的数字多,所以在dp数组中可以不记录3 8这个序列,把这一部分冗余去除。

那么换成与上述状态表示的集合“所有以第i个数结尾的上升子序列集合”的逻辑来讲,相同长度最后结尾的数字越小越好。

需要存储:所有长度对应的最小结尾值,定义一个q[N]数组

 

上图自变量是长度,应变量是该序列对应最小结尾值

可以证明是该数组是单调递增的,因为假设长度为5的序列最小结尾值为10,长度为6的序列最小结尾值为8,那我是不是其实可以把长度为5的序列的10去掉换为8,把长度为6的序列的8去掉换为10啊?所以这种情况如果说代码逻辑存的对的话是不应该发生的,故严格递增。

核心过程:在q数组中找小于a[i]最大的一个数,我们在逻辑上是为了将a[i]插入到该逻辑子序列(候选的最长上升子序列,是我们的目标但是我们不存它的全部,只在q对应长度下标位置存它的最后一位数)的结尾,而q数组正好是存储的该子序列结尾元素,所以最后实际的操作就是“覆盖”掉q数组该位置的元素, 以实现逻辑上的逻辑子序列的后插操作。同样也不用担心“重复覆盖”问题,比如q[1]是否被覆盖两次以上从而造成逻辑子序列逻辑长度与q下标不对应的情况,因为我们在小于a[i]、最大这里对我们找的q下标位置做了确切的定位,只要在q中存在元素比q[1]大的元素q[j]或者边界位置空白,那么a[i]就会跳过q[1]被放在q[j]位置或者右边界处。

#include<iostream>
#include<algorithm>
using namespace std;const int N=100010;
int a[N],q[N];//a存输入进来的数,q每个数组元素位置i的意义为序列长度为i的序列结尾的最小值
int n;int main()
{cin>>n;for(int i=0;i<n;i++)cin>>a[i];int len=0;//q中的元素个数q[0]=-2e9;//哨兵for (int i = 0; i < n; i++){int l=0,r=len;while (l < r)//二分过程,在q中找小于a[i]的最大的一个数{int mid = l + r + 1 >> 1;//+1是为了边界 if (q[mid] < a[i]) l = mid;else r = mid - 1;}len = max(len, r + 1);q[r + 1] = a[i];//不用担心覆盖问题,找到了就该覆盖,在逻辑上是个后插操作//逻辑上在招的对应上升子序列后插,存储上是结尾数字,那就是要赋值给q[r + 1]}cout<<len;return 0;
}


http://www.mrgr.cn/news/99140.html

相关文章:

  • C++ 模块化编程(Modules)在大规模系统中的实践难点
  • acwing--动态规划【线性dp】4/20、4/21
  • 大数据应用开发——大数据平台集群部署(四)
  • 机器学习专栏(4):从数据饥荒到模型失控,破解AI训练的七大生死劫
  • 分布类相关的可视化图像
  • 基于maven-jar-plugin打造一款自动识别主类的maven打包插件
  • 单元测试的一般步骤
  • 20. git diff
  • 超简单的git学习教程
  • Spring Boot 项目中发布流式接口支持实时数据向客户端推送
  • 硬件电路(24)-NE555振荡电路
  • vue的基本结构
  • 用python脚本怎么实现:把一个文件夹里面.png文件没有固定名称,复制到另外一个文件夹按顺序命名?
  • 强制重装及验证onnxruntime-gpu是否正确工作
  • 【Rust 精进之路之第8篇-工具赋能】深入 Cargo:依赖管理、构建配置与工作空间 (Workspace)
  • 【TeamFlow】4 团队管理系统
  • 2.1 基于委托的异步编程方法
  • 2020 年 7 月大学英语四级考试真题(组合卷)——解析版
  • 计算机视觉cv2入门之视频处理
  • 硬件工程师笔记——电子器件汇总大全