【dp笔记】LIS

作者: jenye_ | 来源:发表于2018-07-07 16:22 被阅读0次

课程笔记:程序设计与算法(二)算法基础:dp


Longest Ordered Subsequence

Time Limit: 2000MS Memory Limit: 65536K
Description
A numeric sequence of ai is ordered if a1 < a2 < ... < aN. Let the subsequence of the given numeric sequence (a1, a2, ..., aN) be any sequence (ai1, ai2, ..., aiK), where 1 <= i1 < i2 < ... < iK <= N. For example, sequence (1, 7, 3, 5, 9, 4, 8) has ordered subsequences, e. g., (1, 7), (3, 4, 8) and many others. All longest ordered subsequences are of length 4, e. g., (1, 3, 5, 8).
Your program, when given the numeric sequence, must find the length of its longest ordered subsequence.
Input
The first line of input file contains the length of sequence N. The second line contains the elements of sequence - N integers in the range from 0 to 10000 each, separated by spaces. 1 <= N <= 1000
Output
Output file must contain a single integer - the length of the longest ordered subsequence of the given sequence.

Sample Input
7
1 7 3 5 9 4 8
Sample Output
4

题目描述

解题步骤

1.找子问题

  • “求序列的前n个元素的最长上升子序列的长度”是个子问题。
    但是这样分解子问题,不具有“无后效性”。

    假设F(n) = x,但可能有多个序列满足F(n) = x 。有的序列的最后一个元素比a_{n+1}小,则加上a_{n+1}就能形成更长上升子序;有的序列最后一个元素不比a_{n+1}小……以后的事情受到如何达到状态n的影响,不符合“无后效性”。

  • 一个好的子问题:“求以a_k(k=1,2,3…N)为终点的最长上升子序列”

    一个上升子序列中最右边的那个数,称为该子序列的“终点”。

    虽然这个子问题和原问题形式上并不完全一样,但是只要这N个子问题都解决了,那么这这N个子问题解中,最大的就是子问题的解。

  1. 确定状态

    • 子问题只和一个变量——数字的位置相关,因此序列中的位置k就是“状态”,而状态k对应的"值",就是以a_k为“终点”的最长上升子序列的长度。
      状态共有N个。
  2. 找出状态转移方程

    • maxLen(x)表示以a_k做为“终点”的最长上升子序列的长度那么:

    初始状态:maxLen(1) = 1
    maxLen(k) = max {maxLen (i) :1<=i<k且a_i<a_k且k\neq1} + 1
    maxLen(k)的值,就是在a_k左边,“终点”数值小于a_k,且上都最大的那个上升子序列的长度再加1。因为a_k左边任何“终点”小于a_k的子序列,加上a_k后就能形成一个更长的上升子序列。

时间时间复杂度:状态的数目*找到状态所花的时间:N个状态*N,所以复杂度为O(n^2)

代码实现

#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 100;
int maxLen[MAXN];
int a[MAXN];
int main(){
    int N;
    cin>>N;
    for(int i = 0; i<N ;i++){
        cin>>a[i];
        maxLen[i] = 1;
    }
    for(int i = 1 ;i<N ;i++){
//每次求第a[i]个为终点的lis的长度
        for(int j = 0 ; j<i;j++){
//查看以a[j]为终点的的lis
            if(a[j]<=a[i]){
                maxLen[i] = max(maxLen[i],maxLen[j]+1);
            }
        }
    } //复杂度为O(n*n)
    cout<< * max_element(maxLen,maxLen + N);
    return 0; 
} 

STL之min_element()与max_element


相关文章

  • 【dp笔记】LIS

    课程笔记:程序设计与算法(二)算法基础:dp Longest Ordered Subsequence Time L...

  • HUD1069

    这道题目的思路和LIS相似,但是要注意排序的问题。 接下来是状态转移方程,dp[i]=max(dp[i],dp[j...

  • 最长上升子序列

    算法简述 最长上升子序列(Longest Increasing Subsequence, 简称LIS)是dp中比较...

  • LIS(Substring & subsequence)

    把LIS和LCS对应的总共四种问题总结一下。 Longest Increasing Subsequce:DP,复杂...

  • Chapter11——动态规划——经典问题

    1. 题目列表 POJ3267(字符串匹配dp) POJ1836(LIS最长上升子序列的变形:最长先上升后下降子序...

  • hdu1257(最长上升子序列)

    题目链接:kuanbin带你飞基础dp专题:hdu1257这是一道经典的LIS题目。一句话可以概括这道题目的变形:...

  • 动态规划入门-LIS/LCS(2020-05-21)

    写在前面:学DP掌握基础很重要,这里记录一下LIS和LCS,(希望每次在记录时能够收获新的东西 引入问题: 给定一...

  • LeetCode 142 环形链表 II Linked List

    有关链表的LeetCode做题笔记合集,Python实现 链表定义 142. 环形链表 II Linked Lis...

  • LeetCode-338-比特位计数

    解题思路: 枚举: dp[0]=0; dp[1]=1;dp[2]=1; dp[3]=2;dp[4]=1; dp[5...

  • DP-转移方程

    搞个算法笔记dp的总结,晴神tql了8!!!! 数塔 dp[i][j]为从第i行第j个数字出发的到达最底层的所有路...

网友评论

    本文标题:【dp笔记】LIS

    本文链接:https://www.haomeiwen.com/subject/bkywuftx.html