最长单调递增子序列

解题思想:动态规划

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

 代码:

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. using namespace std;
  5. const int MAX_N = ;
  6. int n;
  7. char a[MAX_N];
  8. int dp[MAX_N];
  9. int main() {
  10. int n;
  11. cin >> n;
  12. while(n--) {
  13. int ans = ;
  14. fill(dp, dp+MAX_N, );
  15. cin >> a;
  16. int len = strlen(a);
  17. for(int i = ; i < len; i++) {
  18. for(int j = ; j < i; j++) {
  19. if(a[j] < a[i]) dp[i] = max(dp[i], dp[j] + );
  20. }
  21. ans = max(ans, dp[i]);
  22. }
  23. cout << ans << endl;
  24. }
  25. return ;
  26. }

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 

 代码:

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. using namespace std;
  5. const int MAX_N = ;
  6. const int INF = ;
  7. int n;
  8. char a[MAX_N];
  9. char dp[MAX_N];
  10. int main() {
  11. int n;
  12. cin >> n;
  13. while(n--) {
  14. fill(dp, dp+MAX_N, INF);
  15. cin >> a;
  16. int len = strlen(a);
  17. for(int i = ; i < len; i++) {
  18. for(int j = ; j < len; j++) {
  19. if(!i || dp[j] >= a[i]) {
  20. dp[j] = a[i]; break;
  21. }
  22. }
  23. }
  24. int ans = ;
  25. while(dp[ans] != INF) ans++;
  26. cout << ans << endl;
  27. }
  28. return ;
  29. }

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]的最大的指针

代码:

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. using namespace std;
  6. const int MAX_N = ;
  7. const int INF = ;
  8. int n;
  9. char a[MAX_N];
  10. char dp[MAX_N];
  11. int main() {
  12. int n;
  13. cin >> n;
  14. while(n--) {
  15. fill(dp, dp+MAX_N, INF);
  16. cin >> a;
  17. int len = strlen(a);
  18. for(int i = ; i < len; i++) {
  19. *lower_bound(dp, dp+len, a[i]) = a[i];
  20. }
  21. cout << lower_bound(dp, dp+len, INF) - dp << endl;
  22. }
  23. return ;
  24. }

动态规划-最长单调递增子序列(dp)的更多相关文章

  1. [C++] 动态规划之矩阵连乘、最长公共子序列、最大子段和、最长单调递增子序列、0-1背包

    一.动态规划的基本思想 动态规划算法通常用于求解具有某种最优性质的问题.在这类问题中,可能会有许多可行解.每一个解都对应于一个值,我们希望找到具有最优值的解. 将待求解问题分解成若干个子问题,先求解子 ...

  2. HD1160FatMouse's Speed(最长单调递增子序列)

    FatMouse's Speed Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  3. 题目:[NOIP1999]拦截导弹(最长非递增子序列DP) O(n^2)和O(n*log(n))的两种做法

    题目:[NOIP1999]拦截导弹 问题编号:217 题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发 ...

  4. [dp]最长单调递增子序列LIS

    https://www.51nod.com/tutorial/course.html#!courseId=12 解题关键: 如果将子序列按照长度由短到长排列,将他们的最大元素放在一起,形成新序列$B\ ...

  5. poj1631Bridging signals(最长单调递增子序列 nlgn)

    Bridging signals Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 12251   Accepted: 6687 ...

  6. 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) ...

  7. nyist oj 214 单调递增子序列(二) (动态规划经典)

    单调递增子序列(二) 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描写叙述 ,a2...,an}(0<n<=100000).找出单调递增最长子序列,并求出其长度 ...

  8. ny214 单调递增子序列(二) 动态规划

    单调递增子序列(二) 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述 给定一整型数列{a1,a2...,an}(0<n<=100000),找出单调递增最长子序 ...

  9. nyoj 214——单调递增子序列(二)——————【二分搜索加dp】

    单调递增子序列(二) 时间限制:1000 ms  |  内存限制:65535 KB 难度:4   描述 给定一整型数列{a1,a2...,an}(0<n<=100000),找出单调递增最长 ...

随机推荐

  1. Android开发代码规范总结

    本篇开始总结Android开发中的一些注意事项,提高代码质量(仅供参考): 1.  Activity间的数据通信,对于数据量比较大的,避免使用 Intent + Parcelable 的方式,可以考虑 ...

  2. SpringBoot整合Graylog3.0

    Graylog简介 Graylog是一个开源的完整的日志管理工具,功能和ELK类似,安装部署更方便. 官方网站 https://www.graylog.org 搭建 使用docker快速搭建 参考 h ...

  3. 浅谈 Java JPDA

    前言 程序员在坊间有非常多有趣的故事,其中就有这么一则:”这个在我的电脑上是好的,没问题的呀,诺,你看咯,一定是你打开姿势不正确,浏览器版本不正确,操作系统不统一等,总之不是我代码问题(傲娇)”.看到 ...

  4. linux安装vmware

    在官网下载linux版 https://www.vmware.com/products/workstation-pro/workstation-pro-evaluation.html sudo chm ...

  5. MySQL学习(六)

    1 注意 select cout(*) from 表名: 查询的就是绝对的行数,哪怕某一列所有字段全部为NULL,也计算在内.而select cout(列名) form 表名:查询的是该列不为null ...

  6. 2017-2018-2 20165327 实验三《敏捷开发与XP实践》实验报告

    2017-2018-2 20165327 实验三<敏捷开发与XP实践>实验报告 实验三 <敏捷开发与XP实践> 一.实验报告封面 课程:Java程序设计 班级:1653 姓名: ...

  7. 20165303学习基础和C语言基础调查

    20165303学习基础和C语言基础调查 技能学习心得 我认为我的乒乓球打的还不错,不能说非常好,但是基本的一些技巧都还是会的,小时候爸爸就非常爱看乒乓球比赛,有时候也带着我一起看,最开始看的时候我发 ...

  8. 关于Mysql 查询所有表的实时记录用于对比2个MySQL 库的数据是否异步

    Xu言: 今天,为了研究一个MySQL主从同步开机后报错 问题,如下图 故障原因分析: 经过分析,可能是主从服务器开机顺序导致.(有待下次断电再次测试) 主从错误提示:日志读取错误的问题.解决方法:更 ...

  9. MySQL数据库索引之B+树

    一.B+树是什么 B+ 树是一种树型数据结构,通常用于数据库和操作系统的文件系统中.B+ 树的特点是能够保持数据稳定有序,其插入与修改操作拥有较稳定的对数时间复杂度.B+ 树元素自底向上插入,这与二叉 ...

  10. arm ncnn

    ncnn网址:https://github.com/Tencent/ncnn 1. sudo apt-get update sudo apt-get upgrade 2. 命令:sudo apt-ge ...