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

在一个已知的序列 {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. Git学习笔记(一) 安装及版本库介绍

    安装Git 最早Git是在Linux上开发的,很长一段时间内,Git也只能在Linux和Unix系统上跑.不过,慢慢地有人把它移植到了Windows上.现在,Git可以在Linux.Unix.Mac和 ...

  2. 下载谷歌浏览器(Chrome)扩展离线安装包crx文件最简单的方法

    转:http://alyzq.com/?p=627 如果不会使用,请看下面的操作步骤 引言(可以不看): 下面介绍一下,下载谷歌浏览器(Google Chrome)扩展的离线安装包crx文件最简单的方 ...

  3. 我们知道写入过程比ZooKeeper集合中的读取过程要贵,因为所有节点都需要在数据库中写入相同的数据。因此,对于平衡的环境拥有较少数量(例如3,5,7)的节点比拥有大量的节点要好。

    我们知道写入过程比ZooKeeper集合中的读取过程要贵,因为所有节点都需要在数据库中写入相同的数据.因此,对于平衡的环境拥有较少数量(例如3,5,7)的节点比拥有大量的节点要好. 组件 描述 写入( ...

  4. 【MyEcplise】导入项目报错:Errors running builder 'JavaScript Validator' on project '项目名'. java.lang.ClassCastException

    导入项目报错:Errors running builder 'JavaScript Validator' on project '项目名'. java.lang.ClassCastException ...

  5. coco2dx jni 调用 java 相机返回 图片数据

    新建 一个项目 名字:testJin  包名:com.TanSon.org  python命令:python create_project.py -project testJin -package c ...

  6. centos6.8下安装部署LNMP(备注:nginx1.8.0+php5.6.10+mysql5.6.12)

    在平时运维工作中,经常需要用到LNMP应用框架.以下对LNMP环境部署记录下: 1)前期准备:为了安装顺利,建议先使用yum安装依赖库[root@opd ~]#yum install -y make ...

  7. git 出现502错误后用depth一步一步来

    公司有个项目的git仓库,因为一些二进制文件也放在里面,版本迭代后,整个仓库特别大,有好几G. 直接git clone是不行的,会报这样的错误: error: RPC failed; HTTP 502 ...

  8. [TypeScript] Dynamically Allocate Function Types with Conditional Types in TypeScript

    Conditional types take generics one step further and allow you to test for a specific condition, bas ...

  9. 倍福TwinCAT(贝福Beckhoff)常见问题(FAQ)-如何让不同的PLC程序分线程运行 TC3

    右击Tasks,添加一个新的Task   可以为这个线程设置自定义的扫描周期   然后在项目上右击添加Referenced Task   在TaskSub1上右击添加现有项,把之气写好的PRG程序绑定 ...

  10. Struts Spring Plugin注意点

    Settings The following settings can be customized. See the developer guide. Setting Description Defa ...