poj之最长递增子序列

题目:POJ 2533   Longest Ordered Subsequence

Description

A numeric sequence of ai is ordered if a1 < a2 < ... < aN. Let the subsequence of the given numeric sequence (a1a2, ..., aN)
be any sequence (ai1ai2, ..., 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.

思路1:最常用的方法是二维的动态规划,dp[i]表示0~i以data[i]结尾的最长递增子序列,则dp[i]等于所有data[i]前面的且比data[i]小的数的最长递增子序列的最大值加1,即dp[i] = max(dp[j]+1,1),其中{j < i && data[j] < data[i]},具体代码如下:

#include<iostream>
#include<vector>
using namespace std;

int LIS(vector<int> data)
{
	int length = data.size(),i,j,res = 1;
	if(length == 0)return 0;
	vector<int> dp(length,1);
	for(i = 1; i < length;++i)
	{
		for(j = 0;j < i;++j)
		{
			if(data[j] < data[i] && dp[j] + 1 > dp[i])dp[i] = dp[j] + 1;//状态转移方程
		}
		if(dp[i] > res)res = dp[i];
	}
	return res;
}

int main()
{
	int n,i;
	while(cin >> n)
	{
		vector<int> data(n);
		for(i = 0; i < n;++i)cin >> data[i];
		cout << LIS(data) << endl;
	}
	return 0;
}

思路2:dp[i]表示长度为i的递增子序列的最大值最小的元素,例如(1,7,3,5,9,4,8),则长度为4的子序列有(1,3,5,9)和(1,3,5,8),则dp[4]为8。这样,我们遍历数组data,利用二分查找把data[i]插入到dp的相应位置上,最后dp的长度即为最大长度,具体如下:

#include<iostream>
#include<vector>
using namespace std;

int LIS(vector<int> data)
{
	int length = data.size(),i,j,res = 1;
	if(length == 0)return 0;
	vector<int> dp(length,0);
	dp[0] = data[0];
	for(i = 1; i < length;++i)
	{
		int left = 0,right = res-1;
		while(left <= right)//寻找以data[i]结尾的最长递增子序列
		{
			int mid = left + ((right - left) >> 1);
			if(dp[mid] < data[i])left = mid + 1;
			else right = mid - 1;
		}
		dp[left] = data[i]; //表示data[i]应该放在长度为left+1的子序列的最后一个元素上
		if(left >= res)res = left+1;//更新最大长度
	}
	return res;
}

int main()
{
	int n,i;
	while(cin >> n)
	{
		vector<int> data(n);
		for(i = 0; i < n;++i)cin >> data[i];
		cout << LIS(data) << endl;
	}
	return 0;
}

poj之最长递增子序列

时间: 2024-11-15 00:31:42

poj之最长递增子序列的相关文章

Bridging signals POJ 1631(最长递增子序列dp)

原题 题目链接 题目分析 由题目知,如果能求出连接点的最长递增子序列,则可以把连接不在该序列中的点的线全部剪掉.而维护最长递增子序列可以用dp来做,考虑到相同长度的递增子序列末尾数字越小越好,可以这样定义dp,dp[i]长度为i的递增子序列的最小末尾值,初始化为INF,由于这个dp具有有序性,因此可以用二分来加快更新,每次遍历到值num[i],只需二分找出大于等于num[i]的更新之即可.最后从扫一遍dp数组即可得到最长长度. 代码 1 #include <iostream> 2 #inclu

POJ 2533 Longest Ordered Subsequence【最长递增子序列】【DP思想】

Longest Ordered Subsequence Time Limit : 4000/2000ms (Java/Other)   Memory Limit : 131072/65536K (Java/Other) Total Submission(s) : 6   Accepted Submission(s) : 1 Problem Description A numeric sequence of ai is ordered ifa1 < a2 < ... < aN. Let t

POJ 1631(最长上升子序列 nlogn).

~~~~ 由题意可知,因为左边是按1~n的顺序递增排列,要想得到不相交组合,左边后面的一定与相应右边后面的相连,如此一来, 就可以发现其实是一道最长上升子序列的题目,要注意的是N<40000,用n^2的算法一定会超时. 题目链接:http://poj.org/problem?id=1631 ~~~~ nlogn的算法在这里补充一下. 最长不下降子序列的O(nlogn)算法分析如下: 设 A[t]表示序列中的第t个数,F[t]表示从1到t这一段中以t结尾的最长上升子序列的长度,初始时设F [t]

最长公共子序列(LCS)、最长递增子序列(LIS)、最长递增公共子序列(LICS)

最长公共子序列(LCS) [问题] 求两字符序列的最长公共字符子序列 问题描述:字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字符序列X=“x0,x1,…,xm-1”,序列Y=“y0,y1,…,yk-1”是X的子序列,存在X的一个严格递增下标序列<i0,i1,…,ik-1>,使得对所有的j=0,1,…,k-1,有xij=yj.例如,X=“ABCBDAB”,Y=“BCDB”是X的一个子序列. 考虑最长公共子序列问题如何分解成

动态规划(DP),最长递增子序列(LIS)

题目链接:http://poj.org/problem?id=2533 解题报告: 状态转移方程: dp[i]表示以a[i]为结尾的LIS长度 状态转移方程: dp[0]=1; dp[i]=max(dp[k])+1,(k<i),(a[k]<a[i]) #include <stdio.h> #define MAX 1005 int a[MAX];///存数据 int dp[MAX];///dp[i]表示以a[i]为结尾的最长递增子序列(LIS)的长度 int main() { int

HDU 3998 Sequence (最长递增子序列+最大流SAP,拆点法)经典

Sequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1666    Accepted Submission(s): 614 Problem Description There is a sequence X (i.e. x[1], x[2], ..., x[n]). We define increasing subsequ

算法面试题 之 最长递增子序列 LIS

找出最长递增序列 O(NlogN)(不一定连续!) 参考 http://www.felix021.com/blog/read.php?1587%E5%8F%AF%E6%98%AF%E8%BF%9E%E6%95%B0%E7%BB%84%E9%83%BD%E6%B2%A1%E7%BB%99%E5%87%BA%E6%9D%A5 我就是理解了一下他的分析 用更通俗易懂的话来说说题目是这样 d[1..9] = 2 1 5 3 6 4 8 9 7 要求找到最长的递增子序列首先用一个数组b[] 依次的将d里面

[网络流24题]最长递增子序列问题

题目大意:给定长度为n的序列a,求:1.最长递增子序列长度:2.最多选出几个不相交的最长递增子序列:3.最多选出几种在除了第1个和第n个以外的地方不相交的最长递增子序列.(n<=1000) 思路:先倒着DP,求出f[i]表示以a[i]开头的最长的递增子序列长度,然后建图,若f[i]=最长递增子序列长度则S向i连1,若f[i]=1则i向T连1,若i<j且a[i]<a[j]且f[i]=f[j]+1则i向j连1,为保证每个点只被流一次,拆成入点和出点,流量限制1,跑最大流即可解决第二问,点1和

最大子数组之和、最大子数组之积、最长递增子序列求法

昨天做爱奇艺笔试题,最后一道编程题是求整型数组最长递增子序列,由于时间关系,没有完全写出来,今天重新来做做这一系列题. <1> 最大子数组之和 首先从最简单的最大子数组之和求取.数组里有正数.负数.零.设包含第 i 个元素的子数组的和为 Sum,则Sum的值为 Sum(i) = Sum(i-1) + arrey[i]; 显然如果arrey[i]<=0,则Sum(i)<=Sum(i-1);则必须把Sum(i)=arrey[i];同时maxSum用来保存Sum最大值.时间复杂度为o(n