LIS入门1

早都想写关于LIS的博客了,可是一直苦于自己不能理解它,所以拖到现在才写。

现在我们先来简单的介绍一下什么是LIS,LIS(Longest Increasing Subsequence)最长上升子序列,LIS也是简单的动态规划问题吧。

什么是最长上升子序列呢?现在我们先随便给一个序列吧。例如:1 7 3 5 9 4 8,他的上升的子序列有好多个例如:1 3 5,1 3 5 9,

1 3 8,但是我们要求的是它的最长的上升子序列,或许最长上升的子序列的个数不止一个,但是最长子序列的长度一定是一个定值吧!我们要求的就是这个最长子序列的长度。

对于求LIS我们有两种方法,一种是复杂度为O(N^2)做法,还有一种复杂度为O(NlogN)做法,在这里我们先学习第一种方法。

O(N^2)做法:dp动态规划:

我们还是用 1 7 3 5 9 4 8这个序列,我们让a[]={1,7,3,5,9,4,8}我们的大致思路就是我们先找以a[0]结尾的LIS,然后再找以a[1]结尾的LIS,以此类推,然后我们从这7个LIS中选择最大的那个,最大的那个就一定是我们要找的这个序列的LIS。我们让dp[i]代表以a[i]结尾的LIS。

我们来模拟一下整个过程,首先我们应该让dp[i]=1.因为每个单独的一个数字他的LIS就是1,然后我们开始:

首先我们看以a[0]结尾的LIS,这毫无疑问,肯定等于1对吧,所以此时dp[0]=1;

然后看a[1],因为a[1]>a[0],所以dp[1]=dp[0]+1;dp[1]=2;

再看a[2],我们先从a[0]开始看,因为 a[2]>a[0],所以dp[2]=dp[0]+1;dp[2]=2;再看a[1],因为  a[2]<a[1],所以不做处理。dp[2]=2。

再看a[3],我们还是先从我们先从a[0]开始看,因为 a[3]>a[0],所以dp[3]=dp[0]+1;dp3]=2;再看a[1],因为  a[23]<a[1]所以不做处理,接着看a[2],,因为 a[3]>a[2],所以dp[3]=dp[2]+1;dp3]=3;现在我们得到了两个dp[3],那么dp[3]到底等于几呢?首先我们要知道我们求得是最长的序列,所以说呢?我们当然要选最大的啊,所以dp[3]=max(2,3),所以dp[3]=3;

下面一次类推,从中我们就可以推出状态转移:dp[i]=max(dp[i], dp[j]+1) (0<=j< i, a[j]< a[i]) 。

下面给一道例题来阐述代码的具体写法:

某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能超过前一发的高度.某天,雷达捕捉到敌国的导弹来袭.由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹. 
怎么办呢?多搞几套系统呗!你说说倒蛮容易,成本呢?成本是个大问题啊.所以俺就到这里来求救了,请帮助计算一下最少需要多少套拦截系统. 

Input

输入若干组数据.每组数据包括:导弹总个数(正整数),导弹依此飞来的高度(雷达给出的高度数据是不大于30000的正整数,用空格分隔) 

Output

对应每组数据输出拦截所有导弹最少要配备多少套这种导弹拦截系统. 

Sample Input

8 389 207 155 300 299 170 158 65

Sample Output

2

 这个题翻译过来就是看给的序列中有几个连续的不下降的子序列,其实这个就等于求LIS,下面给出LIS代码。

#include<stdio.h>
#include<stdio.h>
#include<iostream>
using namespace std;
int a[1003];//用于存放所给的序列
int dp[1003];//表示以i结尾的LIS
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            dp[i]=1;//对dp进行初始化。使得刚开始的LIS为一个数字的LIS  1‘
        }
        int ans=0;
        for(int i=2;i<=n;i++)//以每一个数字结尾时求此时的的LIS
        {
            for(int j=1;j<i;j++)
            {
                if(a[j]<a[i])
                    dp[i]=max(dp[i],dp[j]+1);//求最大值
            }
            ans=max(ans,dp[i]);//找到那个最大的LIS
        }
        printf("%d\n",ans);
    }
    return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值