最长递增子序列是动态规划中最经典的问题之一,我们从讨论这个问题开始,循序渐进的了解动态规划的相关知识要点。

在一个已知的序列 {a1, a 2,...an}中,取出若干数组成新的序列{ai1, ai 2,...aim},其中下标 i1、i2…im保持递增,即新数列中的各个数之间依旧保持原数列中的先后顺序,那么我们称新的序列{ai1, ai 2,...aim}为原序列的一个子序列。若在子序列中,当下标 ix > iy时,aix > aiy,那么我们称这个子序列为原序列的一个递增子序列。最长递增子序列问题,就是在一个给定的原序列中,求得其最长递增子序列长度。

有序列 {a1, a 2,...an},我们求其最长递增子序列长度。按照递推求解的思想,我们用 F[i]代表若递增子序列以 ai结束时它的最长长度。当i较小,我们容易直接得出其值,如 F[1] = 1。那么,如何由已经求得的 F[i]值推得后面的值呢?假设,F[1]到 F[x-1]的值都已经确定,注意到,以ax结尾的递增子序列,除了长度为1的情况,其它情况中,ax都是紧跟在一个由 ai(i<x)组成递增子序列之后。要求以ax结尾的最长递增子序列长度,我们依次比较ax与其之前所有的 ai(i<x),若ai小于ax,则说明ax可以跟在以ai结尾的递增子序列之后,形成一个新的递增子序列。又因为以ai结尾的递增子序列最长长度已经求得,那么在这种情况下,由以ai结尾的最长递增子序列再加上ax得到的新的序列,其长度也可以确定,取所有这些长度的最大值,我们即能得到 F[x]的值。特殊的,当没有ai(i<x)小于 ax,那么以ax结尾的递增子序列最长长度为1。

F[ x] = max{1, F[i] + 1 | ai < ax & &i < x};

我们给出求序列{1,4,3,2,6,5}的最长递增子序列长度的所有 F[i]供读者参考。

F[1](1)

F[2](4)

F[3](3)

F[4](2)

F[5](6)

F[6](5)

1

2

2

2

3

3

总结一下,求最长递增子序列的递推公式为:

F[1] = 1;

F[i] = max{1, F[ j] + 1 | aj < ai & & j < i};

接下来是一个应用的列子,我们通过这个列子,来再度深入的了解下LIS。

某国为了防御敌国的导弹袭击,发展中一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于等于前一发的高度。某天,雷达捕捉到敌国导弹来袭。由于该系统还在试用阶段,所以只用一套系统,因此有可能不能拦截所有的导弹。

输入:
第一行输入测试数据组数N(1<=N<=10)
接下来一行输入这组测试数据共有多少个导弹m(1<=m<=20)
接下来行输入导弹依次飞来的高度,所有高度值均是大于0的正整数。
输出:
输出最多能拦截的导弹数目
样例输入:
2
8
389 207 155 300 299 170 158 65
3
88 34 65
样例输出:
6
2
#include <stdio.h>
int max(int a,int b) {return a > b ? a : b;} //取最大值函数
int list[26]; //按袭击事件顺序保存各导弹高度
int dp[26]; //dp[i]保存以第i个导弹结尾的最长不增子序列长度
int main() {
int n;
while (scanf("%d",&n) != EOF) {
for (int i = 1;i <= n;i ++) {
scanf("%d",&list[i]);
} //输入
for (int i = 1;i <= n;i ++) { //按照袭击时间顺序确定每一个dp[i]
int tmax = 1; //最大值的初始值为1,即以其结尾的最长不增子序列长度至少为1
for (int j = 1;j < i;j ++) { //遍历其前所有导弹高度
if (list[j] >= list[i]) { //若j号导弹不比当前导弹低
tmax = max(tmax,dp[j] + 1); //将当前导弹排列在以j号导弹结尾的最长不增子序列之后,计算其长度dp[j] + 1,若大于当前最大值,则更新最大值
}
}
dp[i] = tmax; //将dp[i]保存为最大值
}
int ans = 1;
for (int i = 1;i <= n;i ++) {
ans = max(ans,dp[i]);
} //找到以每一个元素结尾的最长不增子序列中的最大值,该最大值即为答案
printf("%d\n",ans); //输出
}
return 0;
}  

最长递增子序列问题,是我们接触的第一个真正意义上的动态规划问题。我们来回顾它的特点。首先,我们将这个问题分割成许多子问题,每个子问题为确定以第 i个数字结束的递增子序列最长长度。其次,这些子问题之间存在某种联系,以任意一个数字结束的递增子序列长度,与以排在该数字之前所有比它小的元素结尾的最长递增子序列长度有关,且仅与其数字量有关,而与其具体排列无关。


 

 

 

 

算法之动态规划(最长递增子序列——LIS)的更多相关文章

  1. 动态规划 - 最长递增子序列(LIS)

    最长递增子序列是动态规划中经典的问题,详细如下: 在一个已知的序列{a1,a2,...,an}中,取出若干数组组成新的序列{ai1,ai2,...,aim},其中下标i1,i2,...,im保持递增, ...

  2. 动态规划(DP),最长递增子序列(LIS)

    题目链接:http://poj.org/problem?id=2533 解题报告: 状态转移方程: dp[i]表示以a[i]为结尾的LIS长度 状态转移方程: dp[0]=1; dp[i]=max(d ...

  3. 最长回文子序列LCS,最长递增子序列LIS及相互联系

    最长公共子序列LCS Lintcode 77. 最长公共子序列 LCS问题是求两个字符串的最长公共子序列 \[ dp[i][j] = \left\{\begin{matrix} & max(d ...

  4. 2.16 最长递增子序列 LIS

    [本文链接] http://www.cnblogs.com/hellogiser/p/dp-of-LIS.html [分析] 思路一:设序列为A,对序列进行排序后得到B,那么A的最长递增子序列LIS就 ...

  5. 一个数组求其最长递增子序列(LIS)

    一个数组求其最长递增子序列(LIS) 例如数组{3, 1, 4, 2, 3, 9, 4, 6}的LIS是{1, 2, 3, 4, 6},长度为5,假设数组长度为N,求数组的LIS的长度, 需要一个额外 ...

  6. 动态规划----最长递增子序列问题(LIS)

    题目: 输出最长递增子序列的长度,如输入 4 2 3 1 5 6,输出 4 (因为 2 3 5 6组成了最长递增子序列). 暴力破解法:这种方法很简单,两层for循环搞定,时间复杂度是O(N2). 动 ...

  7. 最长递增子序列 LIS 时间复杂度O(nlogn)的Java实现

    关于最长递增子序列时间复杂度O(n^2)的实现方法在博客http://blog.csdn.net/iniegang/article/details/47379873(最长递增子序列 Java实现)中已 ...

  8. 最长递增子序列LIS再谈

    DP模型: d(i) 以第 i 个元素结尾的最长递增子序列的长度. 那么就有 d(i) = max(d(j)) + 1;(j<i&&a[j]<a[i]),答案 max(d( ...

  9. 算法面试题 之 最长递增子序列 LIS

    找出最长递增序列 O(NlogN)(不一定连续!) 参考 http://www.felix021.com/blog/read.php?1587%E5%8F%AF%E6%98%AF%E8%BF%9E%E ...

随机推荐

  1. ntp流量放大攻击分析

    最近,听说挂在网络上的设备进行时间同步成功率低,YS需要架设自己的NTP服务器,这玩意第一时间能让人想到NTP流量放大攻击,这也是一种比较古老的攻击方式,检测了一下发现所使用的OS默认已经进行了加固, ...

  2. Zookeeper的功能以及工作原理(转)

    本文转自https://www.cnblogs.com/felixzh/p/5869212.html Zookeeper的功能以及工作原理   1.ZooKeeper是什么?ZooKeeper是一个分 ...

  3. 【spring data jpa】jpa实现update操作 字段有值就更新,没值就用原来的

    示例代码如下: /** *复杂JPA操作 使用@Query()自定义sql语句 根据业务id UId去更新整个实体 * 删除和更新操作,需要@Modifying和@Transactional注解的支持 ...

  4. Coherence的集群成员的离开和加入机制研究

    最近在客户那里环境中coherence集群不稳定,所以找出一些文档,需要搞清楚Coherence内部的一些机制 1.集群成员的离开 关于状态的检测,官方的说法是: Death detection is ...

  5. Sqoop操作实践

    Sqoop操作实践 @(Hadoop) Sqoop常用参命令 序号 命令/command 类 说明 1 impor ImportTool 从关系型数据库中导入数据(来自表或者查询语句)到HDFS中 2 ...

  6. 转:facebook 开源工具集合

    http://codekk.com/blogs/detail/Trinea/Facebook%20%E7%9A%84%E9%82%A3%E4%BA%9B%E5%BC%80%E6%BA%90%E9%A1 ...

  7. Node.js meitulu图片批量下载爬虫1.02版

    以前版本需要先查看网页源码,然后肉眼找到图片数量和子目录,虽说不费事,但多少有点不方便. 于是修改了一下,用cheerio自己去找找到图片数量和子目录,只要修改页面地址就行了.至此社会又前进了一步. ...

  8. 来自 119.*.*.*的回复: TTL 传输中过期

    来自 119.*.*.*的回复: TTL 传输中过期. 一般这种情况是由于路由表问题造成的. tracert命令跟踪了一下,有如下输出: C:\Users\cba>tracert 119.*.* ...

  9. static_cast、dynamic_cast、const_cast和reinterpret_cast总结(转)

    前言 这篇文章总结的是C++中的类型转换,这些小的知识点,有的时候,自己不是很注意,但是在实际开发中确实经常使用的.俗话说的好,不懂自己写的代码的程序员,不是好的程序员:如果一个程序员对于自己写的代码 ...

  10. Kubernetes使用prometheus+grafana做一个简单的监控方案

    前言 本文介绍在k8s集群中使用node-exporter.prometheus.grafana对集群进行监控.其实现原理有点类似ELK.EFK组合.node-exporter组件负责收集节点上的me ...