动态规划-最长单调递增子序列(dp)
解题思想:动态规划
1.解法1(n2)
状态:d[i] = 长度为i+1的递增子序列的长度
状态转移方程:dp[i] = max(dp[j]+1, dp[i]);
分析:最开始把dp数组初始化为1,然后从前往后考虑数列的元素,对于每个aj,如果a[i] > a[j],就用dp[i] = max(dp[i], dp[j] + 1)进行更新,再从dp数组中找出最大值即为结果
举例:abklmncdefg
dp[0] = 1; dp[1] = 2; dp[2] = 3; dp[3] = 4; dp[4] = 5; dp[5] = 6; dp[7] = 3; dp[8] = 4; dp[9] = 5; dp[10] = 6; dp[11] = 7; 最大值为7
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAX_N = ;
int n;
char a[MAX_N];
int dp[MAX_N];
int main() {
int n;
cin >> n;
while(n--) {
int ans = ;
fill(dp, dp+MAX_N, );
cin >> a;
int len = strlen(a);
for(int i = ; i < len; i++) {
for(int j = ; j < i; j++) {
if(a[j] < a[i]) dp[i] = max(dp[i], dp[j] + );
}
ans = max(ans, dp[i]);
}
cout << ans << endl;
}
return ;
}
2.解法2(n2)
状态:d[i] = 长度为i+1的递增子序列中末尾的最小值(不存在就是INF)
分析:最开始用INF初始化dp数组的值,然后从前往后考虑数列的元素,对于每个aj,如果i = 0或者a[j] >= a[i],使得a[j] = a[i]并且break出来,最后第一个dp数组中值为INF的下标即为结果
举例:abklmncdefg
a; ab; abk; abkl; abklm; abklmn; abclmn; abcdmn; abcden; abcdef; abcdefg; 第一个INF的下标为7
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAX_N = ;
const int INF = ;
int n;
char a[MAX_N];
char dp[MAX_N];
int main() {
int n;
cin >> n;
while(n--) {
fill(dp, dp+MAX_N, INF);
cin >> a;
int len = strlen(a);
for(int i = ; i < len; i++) {
for(int j = ; j < len; j++) {
if(!i || dp[j] >= a[i]) {
dp[j] = a[i]; break;
}
}
}
int ans = ;
while(dp[ans] != INF) ans++;
cout << ans << endl;
}
return ;
}
3.解法3(nlogn)
分析:思路与解法2一样,但是解法2可以进一步优化,在解法2中dp数组是单调递增的,每次要从头到尾找到第一个大于等于a[i]的值,这是o(n2)的,既然是顺序的可以使用二分查找进行改进,
这样可以在o(nlogn)时间内求出结果,这里利用到了STL中的lower_bound(dp, dp + n, a[i]),找出dp数组中大于等于a[i]的最小的指针,upper_boundlower_bound(dp, dp + n, a[i]),找出dp数组中大于a[i]的最大的指针
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAX_N = ;
const int INF = ;
int n;
char a[MAX_N];
char dp[MAX_N];
int main() {
int n;
cin >> n;
while(n--) {
fill(dp, dp+MAX_N, INF);
cin >> a;
int len = strlen(a);
for(int i = ; i < len; i++) {
*lower_bound(dp, dp+len, a[i]) = a[i];
}
cout << lower_bound(dp, dp+len, INF) - dp << endl;
}
return ;
}
动态规划-最长单调递增子序列(dp)的更多相关文章
- [C++] 动态规划之矩阵连乘、最长公共子序列、最大子段和、最长单调递增子序列、0-1背包
一.动态规划的基本思想 动态规划算法通常用于求解具有某种最优性质的问题.在这类问题中,可能会有许多可行解.每一个解都对应于一个值,我们希望找到具有最优值的解. 将待求解问题分解成若干个子问题,先求解子 ...
- HD1160FatMouse's Speed(最长单调递增子序列)
FatMouse's Speed Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...
- 题目:[NOIP1999]拦截导弹(最长非递增子序列DP) O(n^2)和O(n*log(n))的两种做法
题目:[NOIP1999]拦截导弹 问题编号:217 题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发 ...
- [dp]最长单调递增子序列LIS
https://www.51nod.com/tutorial/course.html#!courseId=12 解题关键: 如果将子序列按照长度由短到长排列,将他们的最大元素放在一起,形成新序列$B\ ...
- poj1631Bridging signals(最长单调递增子序列 nlgn)
Bridging signals Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 12251 Accepted: 6687 ...
- NYOJ17 最长单调递增子序列 线性dp
题目链接: http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=17 分析: i=1 dp[i]=1 i!=1 dp[i]=max(dp[j]+1) ...
- nyist oj 214 单调递增子序列(二) (动态规划经典)
单调递增子序列(二) 时间限制:1000 ms | 内存限制:65535 KB 难度:4 描写叙述 ,a2...,an}(0<n<=100000).找出单调递增最长子序列,并求出其长度 ...
- ny214 单调递增子序列(二) 动态规划
单调递增子序列(二) 时间限制:1000 ms | 内存限制:65535 KB 难度:4 描述 给定一整型数列{a1,a2...,an}(0<n<=100000),找出单调递增最长子序 ...
- nyoj 214——单调递增子序列(二)——————【二分搜索加dp】
单调递增子序列(二) 时间限制:1000 ms | 内存限制:65535 KB 难度:4 描述 给定一整型数列{a1,a2...,an}(0<n<=100000),找出单调递增最长 ...
随机推荐
- django表单的Widgets
不要将Widget与表单的fields字段混淆.表单字段负责验证输入并直接在模板中使用.而Widget负责渲染网页上HTML表单的输入元素和提取提交的原始数据.widget是字段的一个内在属性,用于定 ...
- [原][源码][tinyxml][opencv]按照规格剪切所有的图片
源码: #include <iostream> #include <fstream> #include <opencv2/core/core.hpp> #inclu ...
- .NET扩展方法 封装公用方法
定义方法的时候 第一个参数前面加上this 表示这个方法可以被IQueryable类型的对象.出来 调用的时候 只用传第二个参数 第一个参数不用传 第一个参数就是.出当前方法的参数 定义扩展 ...
- Java String常用的两个方法
- anusplina 4.36版本使用提示 说明
1),必须要注意的是,你生成的dat文件中,第一列必须是气象站点编号:第二列必须是经度数值,而且是投影坐标下,以 米 为单位:第三列必须是纬度了:第四列必须是海拔了:之后就是你自己的数据,比如平均温度 ...
- 利用vue-cli3快速搭建vue项目详细过程
一.介绍 Vue CLI 是一个基于 Vue.js 进行快速开发的完整系统.有三个组件: CLI:@vue/cli 全局安装的 npm 包,提供了终端里的vue命令(如:vue create .vue ...
- nRF52832-PPI部分学习
PPI部分学习思维导图 PPI原理 1.1PPI简介 PPI实现的就是通过初始化配置,将不同外设的事件和任务连接起来,让事件自动去触发任务的功能,PPI有多个通道, 每个通道包含一个EEP和TEP,使 ...
- Asp.net core 学习笔记 ( OData )
2018-12-10 更新 : 从前我都是把 entity 直接用于 odata 曝露 api 给程序用. 如果这个程序是我们自己写的前端,这样的方式非常好,因为就好比前端可以直接对数据库每一个表做操 ...
- Python 编程快速上手 第十一章 Web scrapping
前言 这一章讲了如何在 Web 上抓取相关的信息,工具是三个模块: webbrowser 模块:用于打开浏览器指定页面 requests 模块:用于下载文件 Beautiful Soup 模块:用于解 ...
- Python 编程快速上手 第十五章 保持时间,计划任务和启动程序
前言 这一章节的主要内容是: 处理时间类型的数据(使用python 的两个模块: time 和 datetime 来处理) 创建多个线程 (使用 threading 模块来创建多个线程) 进行多个进程 ...