动态规划-最长非降子序列

有关概念:

  最长上升子序列(LIS,Longest Increasing Subsequence),在一个序列中最长的单调递增的子序列

思路:
  求LIS通常有O(n2)和O(nlogn)两种算法

(1)O(n2)算法

  fi表示以第i个数结尾的LIS长度

  对于序列中的一个数i,在i前面枚举数j,j满足比i小且fj最大,将i作为j的后继

  伪代码&状态转移方程:

  f1=1

  for i=2...n

    for j=1...i-1

      if(aj<ai)fi=max(fi,fj+1)

  最后结果在f1~fn中取最大值

  当然,可以在更新fi的时候顺便记录j的位置,在最后可以输出整个LIS

 1 #include<cstdio>
 2 #define MAXN
 3 int n,a[MAXN],f[MAXN],ans;
 4 inline int max(int x,int y)
 5 {
 6     return x>y?x:y;
 7 }
 8 int main()
 9 {
10     scanf("%d",&n);
11     for(int i=1;i<=n;++i)
12     {
13         scanf("%d",&a[i]);
14         f[i]=1;
15     }
16     for(int i=2;i<=n;++i)
17         for(int j=1;j<i;++j)
18             if(a[i]>=a[j]&&f[j]+1>=f[i])f[i]=f[j]+1;
19     for(int i=1;i<=n;++i)ans=max(ans,f[i]);
20     printf("%d",ans);
21     return 0;
22 }

(2)O(nlogn)算法

  fi表示长度为i的非降子序列的最小末尾,len记录当前最长的非降子序列长度

  可得f1<=f2<=f3<=...<=fmaxlen

  每次读入一个数字k,先与flen比较,如果大于则添加至f++len,作为原来flen的后继

  否则在f中找到fi<k<=fi+1,更新为fi+1为k,即k比原来fi+1更优,可作为fi的后继

  最后输出len即可

  然而查找过程可以用二分优化,就得出这种算法

 (样例推导见大犇博客http://www.cnblogs.com/ziyi--caolu/p/3227121.html

 1 #include<cstdio>
 2 #define MAXN
 3 int n,s[MAXN],f[MAXN],len;
 4 int main()
 5 {
 6     scanf("%d",&n);
 7     scanf("%d",&s[1]);
 8     f[1]=s[1];
 9     for(int i=2;i<=n;++i)
10     {
11         scanf("%d",&s[i]);
12         if(s[i]>f[len])f[++len]=s[i];
13         else
14         {
15             int l=1,r=len;
16             while(l<r)
17             {
18                 int mid=(l+r)>>1;
19                 if(s[i]>f[mid])l=mid+1;
20                 else r=mid;
21             }
22             f[l]=s[i];
23         }
24     }
25     printf("%d",len);
26     return 0;
27 }
时间: 2024-11-10 01:28:10

动态规划-最长非降子序列的相关文章

【一维偏序】【最长上升子序列】【最长非降子序列】

两种方法,都是nlogn 树状数组型 #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; const int N=100003,M=50003; int d[N];//原数组 int f[M]; int n,big; int lowbit(int x) { return x&(-x); } //用于求上升序列 int

最长非降/下降子序列问题(DP)(待续...)

注意:抽象成以下描述即为最长非降/下降子序列问题(一维状态) 问题描述:在一个无序的序列a1,a2,a3,a4…an里,找到一个最长的序列满足:(不要求连续) ai<=aj<=ak…<=am,且i<j<k…<m.(最长非降子序列) 或 ai>aj>ak…>am,且i<j<k…<m.(最长下降子序列). 问题分析:(以最长非降子序列为例) 考虑状态数组opt[maxn]; 其中opt[i]表示a[i]时可与之前元素构成非降子序列的最大长

最长上升非降子序列的长度动态规划

第一种dp从后往前: dp[i]表示以a[i]为起点的最长上升非降子序列的长度 a[8]={10,2,2,4,12,23,34,2} dp[8]={4,6,5,4,3,2,1,1}; 代码实现: 1 #include<bits/stdc++.h> 2 using namespace std; 3 void logest_increase_sub(const int*a,int ssize) 4 { 5 int *dp=new int[ssize](); 6 int *p=new int[ssi

HDU 1025 Constructing Roads In JGShining&#39;s Kingdom[动态规划/nlogn求最长非递减子序列]

Constructing Roads In JGShining's Kingdom Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 27358    Accepted Submission(s): 7782 Problem Description JGShining's kingdom consists of 2n(n is no mor

最长不降子序列

最长不降子序列   原文http://www.cppblog.com/superKiki/archive/2010/08/09/122868.html 这题目是经典的DP题目,也可叫作LIS(Longest Increasing Subsequence)最长上升子序列或者 最长不下降子序列.很基础的题目,有两种算法,复杂度分别为O(n*logn)和O(n^2) . 一.问题描述 设有由n个不相同的整数组成的数列,记为: a(1).a(2).--.a(n)且a(i)<>a(j) (i<&g

动态规划——最长不下降子序列(LIS)

最长不降子序列是这样一个问题: 下面介绍动态规划的做法. 令 dp[i] 表示以 A[i] 结尾的最长不下降序列长度.这样对 A[i] 来说就会有两种可能: 如果存在 A[i] 之前的元素 A[j] (j<i),使得 A[j]≤A[i] 且 dp[j]+1>dp[i],那么就把 A[i] 跟在以 A[j] 结尾的 LIS 后面,形成一条更长的不下降子序列(令 dp[i]=dp[j]+1). 如果 A[i] 之前的元素都比 A[i] 大,那么 A[i] 就只好自己形成一条 LIS,但是长度为 1

[LeetCode] Longest Uncommon Subsequence I 最长非共同子序列之一

Given a group of two strings, you need to find the longest uncommon subsequence of this group of two strings. The longest uncommon subsequence is defined as the longest subsequence of one of these strings and this subsequence should not be any subseq

Codeforces Round #323 (Div. 2) D. Once Again... 暴力+最长非递减子序列

                                                                              D. Once Again... You are given an array of positive integers a1, a2, ..., an × T of length n × T. We know that for any i > n it is true that ai = ai - n. Find the length of

最长非上升子序列的长度

最长非上升子序列问题是一个经典的DP问题.如下给出完整的问题描述: 给你一串序列 A1,A2,A3,A4,A5........An.让你找出它的某个最长子序列 S1,S2,S3,S4.........Sm.使得 S1<=S2<=S3<=S4.........<=Sm. 从问题描述中,我们可以把 <= 换成各种其他的关系符号从而变成最长非下降子序列等,他们都只是关系描述不同,其本质都是一样的.现在,我们来只需总结一下最长非上升子序列问题即可应用到其他类型. 这既然是一个经典的D