最长上升子序列&&最长不下降子序列
百练2757: 
题目描述: 
对于给定的序列,求出最长上升子序列的长度。
题目链接:http://bailian.openjudge.cn/practice/2757
解题思路
一、动态规划 
 1. 找子问题
错误找法: 
“求序列的前n个元素的最长上升子序列的长度”是个子问题,但这样分解子问题,不具有“无后效性”   假设F(n) = x,但可能有多个序列满足F(n) = x。有的 序列的最后一个元素比 an+1小,则加上an+1就能形成更长上 升子序列;有的序列最后一个元素不比an+1小……以后的事 情受如何达到状态n的影响,不符合“无后效性”。
正确找法: 
“求以ak(k=1, 2, 3…N)为终点的最长上升子序列的 长度”    一个上升子序列中最右边的那个数,称为该子序列的 “终点”。  虽然这个子问题和原问题形式上并不完全一样,但 是只要这N个子问题都解决了,那么这N个子问题的解中, 最大的那个就是整个问题的解。
2. 确定状态
子问题只和一个变量– 数字的位置相关。因此序列中数 的位置k 就是“状态”,而状态 k 对应的“值”,就是以ak 做为“终点”的最长上升子序列的长度。状态一共有N个。
3.找出状态转移方程
maxLen (k)表示以ak做为“终点”的  最长上升子序列的长度 
那么有: 
maxLen (1) = 1 
maxLen (k) = max { maxLen (i):1<=i < k 且 ai < ak且 k≠1 } + 1                 若找不到这样的i,则maxLen(k) = 1 
maxLen(k)的值,就是在ak左边,“终点”数值小于ak ,且长度 最大的那个上升子序列的长度再加1。因为ak左边任何“终点”小于 ak的子序列,加上ak后就能形成一个更长的上升子序列。
“人人为我”递推型动归程序
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int main()
{
int a[],n;
int maxlen[];
cin>>n;
for(int i=;i<=n;i++)
{
cin>>a[i];
maxlen[i]=;
}
for(int i=;i<=n;i++)
{
for(int j=;j<i;j++)
{
if(a[i]>a[j])
{
maxlen[i]=max(maxlen[i],maxlen[j]+); }
}
}
cout<<* max_element(maxlen+,maxlen++n)<<endl;
return ;
}
二、最长上升子序列 (LIS算法(nlong(n)))
设 A[t]表示序列中的第t个数,F[t]表示从1到t这一段中以t结尾的最长上升子序列的长度,初始时设F [t] = 0(t = 1, 2, …, len(A))。则有动态规划方程:F[t] = max{1, F[j] + 1} (j = 1, 2, …, t - 1, 且A[j] < A[t])。
现在,我们仔细考虑计算F[t]时的情况。假设有两个元素A[x]和A[y],满足 
(1)x < y < t  
(2)A[x] < A[y] < A[t]  
(3)F[x] = F[y]
此时,选择F[x]和选择F[y]都可以得到同样的F[t]值,那么,在最长上升子序列的这个位置中,应该选择A[x]还是应该选择A[y]呢?
很明显,选择A[x]比选择A[y]要好。因为由于条件(2),在A[x+1] … A[t-1]这一段中,如果存在A[z],A[x] < A[z] < a[y],则与选择A[y]相比,将会得到更长的上升子序列。  
再根据条件(3),我们会得到一个启示:根据F[]的值进行分类。对于F[]的每一个取值k,我们只需要保留满足F[t] = k的所有A[t]中的最小值。设D[k]记录这个值,即D[k] = min{A[t]} (F[t] = k)。
注意到D[]的两个特点:  
(1) D[k]的值是在整个计算过程中是单调不下降的。  
(2) D[]的值是有序的,即D[1] < D[2] < D[3] < … < D[n]。
利 用D[],我们可以得到另外一种计算最长上升子序列长度的方法。设当前已经求出的最长上升子序列长度为len。先判断A[t]与D[len]。若A [t] > D[len],则将A[t]接在D[len]后将得到一个更长的上升子序列,len = len + 1, D[len] = A [t];否则,在D[1]..D[len]中,找到最大的j,满足D[j] < A[t]。令k = j + 1,则有A [t] <= D[k],将A[t]接在D[j]后将得到一个更长的上升子序列,更新D[k] = A[t]。最后,len即为所要求的最长上 升子序列的长度。
在 上述算法中,若使用朴素的顺序查找在D[1]..D[len]查找,由于共有O(n)个元素需要计算,每次计算时的复杂度是O(n),则整个算法的 时间复杂度为O(n^2),与原来的算法相比没有任何进步。但是由于D[]的特点(2),我们在D[]中查找时,可以使用二分查找高效地完成,则整个算法 的时间复杂度下降为O(nlogn),有了非常显著的提高。需要注意的是,D[]在算法结束后记录的并不是一个符合题意的最长上升子序列!
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std; const int mx=;
int d[mx];
int main()
{
int n, T;
while (scanf("%d",&n)!=EOF)
{
memset(d, , sizeof(d));
int len = , x;
for (int i=;i<n;i++)
{
scanf("%d", &x);
if(i == )d[++len] = x;
else
{
if(x > d[len])d[++len] = x;///如果是不下降,这里改为>=
else{
int pos = lower_bound(d + , d + len, x) - d;///如果是不下降,这里改为upper_bound(d + 1, d + len, x) - d;
d[pos] = x;
}
}
}
printf("%d\n",len);
}
}
最长上升子序列&&最长不下降子序列的更多相关文章
- 最长下降子序列O(n^2)及O(n*log(n))解法
		
求最长下降子序列和LIS基本思路是完全一样的,都是很经典的DP题目. 问题大都类似于 有一个序列 a1,a2,a3...ak..an,求其最长下降子序列(或者求其最长不下降子序列)的长度. 以最长下降 ...
 - 最长不下降子序列(LIS)
		
最长上升子序列.最长不下降子序列,解法差不多,就一点等于不等于的差别,我这里说最长不下降子序列的. 有两种解法. 一种是DP,很容易想到,就这样: REP(i,n) { f[i]=; FOR(j,,i ...
 - 最长不下降子序列 O(nlogn) || 记忆化搜索
		
#include<stdio.h> ] , temp[] ; int n , top ; int binary_search (int x) { ; int last = top ; in ...
 - BUY LOW, BUY LOWER_最长下降子序列
		
Description The advice to "buy low" is half the formula to success in the bovine stock mar ...
 - tyvj 1049 最长不下降子序列 n^2/nlogn
		
P1049 最长不下降子序列 时间: 1000ms / 空间: 131072KiB / Java类名: Main 描述 求最长不下降子序列的长度 输入格式 第一行为n,表示n个数第二行n个数 输出格式 ...
 - 最长不下降子序列的O(n^2)算法和O(nlogn)算法
		
一.简单的O(n^2)的算法 很容易想到用动态规划做.设lis[]用于保存第1~i元素元素中最长不下降序列的长度,则lis[i]=max(lis[j])+1,且num[i]>num[j],i&g ...
 - 最长不下降子序列//序列dp
		
最长不下降子序列 时间: 1000ms / 空间: 131072KiB / Java类名: Main 描述 求最长不下降子序列的长度 输入格式 第一行为n,表示n个数第二行n个数 输出格式 最长不下降 ...
 - 【tyvj】P1049 最长不下降子序列
		
时间: 1000ms / 空间: 131072KiB / Java类名: Main 描述 求最长不下降子序列的长度 输入格式 第一行为n,表示n个数 第二行n个数 输出格式 最长不下降子序列的长度 测 ...
 - hdu 4604 Deque(最长不下降子序列)
		
从后向前对已搜点做两遍LIS(最长不下降子序列),分别求出已搜点的最长递增.递减子序列长度.这样一直搜到第一个点,就得到了整个序列的最长递增.递减子序列的长度,即最长递减子序列在前,最长递增子序列在后 ...
 - 最长不下降子序列nlogn算法详解
		
今天花了很长时间终于弄懂了这个算法……毕竟找一个好的讲解真的太难了,所以励志我要自己写一个好的讲解QAQ 这篇文章是在懂了这个问题n^2解决方案的基础上学习. 解决的问题:给定一个序列,求最长不下降子 ...
 
随机推荐
- windows系统打开火狐浏览器提示“无法加载你的firefox配置文件”
			
win7系统自带IE浏览器,还是有部分用户使用不习惯,选择下载第三方浏览器,比如:火狐.谷歌.360浏览器等.最近有Win7系统用户在重新安装火狐浏览器后发现打不开,并提示“无法加载你的firefox ...
 - Oracle 12c DG备库Alert报错ORA-01110
			
环境是12.2.0.1 version, Oracle Data Guard备库近段时间一直报错,但是备库主库同步一致,数据一致. 2019-03-06T23:42:22.184048+08:00 E ...
 - Linux 系统 文件锁  fcntl函数详解
			
#include <unistd.h> #include <fcntl.h> int fcntl(int fd, int cmd); int fcntl(int fd, int ...
 - SigmoidCrossEntropyLoss
			
http://blog.csdn.net/u012235274/article/details/51361290
 - [转]AngularJS 使用 UI Router 实现表单向导
			
本文转自:http://www.oschina.net/translate/angularjs-multi-step-form-using-ui-router 今天我们将使用AngularJs和伟大的 ...
 - C语言实现通用链表初步(一)
			
注意:本文讨论的是无头单向非循环链表. 假设不采用Linux内核链表的思路,怎样用C语言实现通用链表呢? 一种常用的做法是: typedef int element_t; struct node_in ...
 - pat03-树1. 二分法求多项式单根(20)
			
03-树1. 二分法求多项式单根(20) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 杨起帆(浙江大学城市学院) 二分法求函数根的 ...
 - net图片转格式
			
http://blog.csdn.net/nrlovestudy/article/details/48137339 图片转格式 Bitmap bmp=new Bitmap("filename ...
 - node.js运行环境变量配置
			
-----Windows cmd---------- 1. echo %PATH% 输出Path环境变量 2.set NODE_ENV=testing 定义环境变量 3.echo %NODE_ENV ...
 - SpringBoot 使用fastjson
			
spring boot默认使用的json解析框架是jackson,替换为fastjson有两种方式 1.继承WebMvcConfigurerAdapter @SpringBootApplication ...