zoukankan      html  css  js  c++  java
  • 最长上升子序列(动态规划递推,LIS)

    1759:最长上升子序列

    题目:

    总时间限制:
    2000ms
    内存限制:
    65536kB
    描述
    一个数的序列bi,当b1 < b2 < ... < bS的时候,我们称这个序列是上升的。对于给定的一个序列(a1, a2, ..., aN),我们可以得到一些上升的子序列(ai1, ai2, ..., aiK),这里1 <= i1 < i2 < ... < iK <= N。比如,对于序列(1, 7, 3, 5, 9, 4, 8),有它的一些上升子序列,如(1, 7), (3, 4, 8)等等。这些子序列中最长的长度是4,比如子序列(1, 3, 5, 8).

    你的任务,就是对于给定的序列,求出最长上升子序列的长度。
    输入
    输入的第一行是序列的长度N (1 <= N <= 1000)。第二行给出序列中的N个整数,这些整数的取值范围都在0到10000。
    输出
    最长上升子序列的长度。
    样例输入
    7
    1 7 3 5 9 4 8
    样例输出
                   4
    下面放一下ac代码
    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const ll maxn=1000+10;
    ll f[maxn];//用来递推的数组
    ll a[maxn];//存储输入数据
    
    int main()
    {
        ll n;
        cin>>n;
        for(ll i=1;i<=n;i++)
        {
            scanf("%lld",&a[i]);//输入数据
            f[i]=1;//顺便为f数组赋初值
            /*
            f数组的意义是以a[i]结尾的序列能拥有的最大长度
            */
        }
    
        for(ll i=2;i<=n;i++)//i=1时f[1]肯定等于1,所以从2开始
            for(ll j=1;j<=i-1;j++)//j代表枚举f[i]前面的所有可能
            {
                if(a[i]>a[j])//如果可以加在它后面,记住这里的子序列是可以间断的
                    f[i]=max(f[i],f[j]+1);
            }
        ll ans=f[1];//为ans初定义
        for(ll i=2;i<=n;i++)//这里的意思是找出f[i=1~n]的最大值
            if(f[i]>ans)
                ans=f[i];
        cout<<ans<<endl;
    }
    点击打开折叠代码

    然后开始解释一下这道题

    我们建立一个数组f[maxn],

    f数组的意义是以a[i]结尾的序列能拥有的最大上升长度

    毫无疑问f[1]始终=1,然后我们对其他f[i]也都赋初始值为1,因为,如果f[i]就只包括a[i]一个的话长度就是1呀

    然后核心是状态转移方程

     if(a[i]>a[j])//如果可以加在它后面,记住这里的子序列是可以间断的
                    f[i]=max(f[i],f[j]+1);
    先说明j=1~i-1,因为a[i]只能拼接在它前面的序列嘛,所以j最大为i-1
    解释一下这段代码:
    if(a[i]>a[j])就是说可以拼接,因为符合上升条件
    然后f[i]=max(f[i],f[j]+1);这里这段语句可能会执行几次,所以有f[i]=max(f[i],....)这样的东西,就是新的自己和旧的自己比较的意思,我们平时用的a=a+1,也是这样,两个a不一样,a=a+1这个栗子是教练教我的,讲的真好
    然后f[i]=max(f[i],f[j]+1)的意思就是在前面已经判断了可以拼接的基础上,如果加在前面的f[j]序列上更长的话就f[i]=f[j]+1(+1的意思是相对于前面的f[j]长度又多了一个,也就是多了a[i]),否则就f[i]=f[i]不变

    推荐一道类似的题目:

    最大子段和(洛谷P1115,动态规划递推)

    
    
  • 相关阅读:
    沈逸老师PHP魔鬼特训笔记(1213) --异形
    《nodejs+gulp+webpack基础实战篇》课程笔记(五)-- 实战演练,构建用户登录
    《nodejs+gulp+webpack基础实战篇》课程笔记(四)-- 实战演练
    《nodejs+gulp+webpack基础实战篇》课程笔记(三)--webpack篇
    沈逸老师PHP魔鬼特训笔记(11)
    《nodejs+gulp+webpack基础实战篇》课程笔记(二)--gulp速度上手
    《nodejs+gulp+webpack基础实战篇》课程笔记(一)--开开脑,走走简单的基础
    沈逸老师PHP魔鬼特训笔记(10)
    沈逸老师PHP魔鬼特训笔记(9)--进化
    Alt.js的入门
  • 原文地址:https://www.cnblogs.com/zyacmer/p/9971485.html
Copyright © 2011-2022 走看看