您的位置:首页 > 其它

最长递增子序列问题

2017-09-06 14:26 302 查看
[align=left]POJ 2533(Longest Ordered Subsequence)
[/align]
[align=center]
[/align]
[align=center]Longest Ordered Subsequence[/align]

Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 55194 Accepted: 24749
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


题目描述:题意就是求一段数字序列中的最长递增序列

解题分析:首先,样例分析有数字序列sub[1005],由于本题最大数字的长度为1000,所以此题可以允许我们在O(n^2)的 时间复杂度,对于此题,我们首先推出递推式,我们首先创立一个数组 maxt[1005],a[0]代表第一个元素,a[1]代表到第二个元素的最长递增子序列,a[2]表示到第三个元素的最长递增子序列,a[3]表示到第四个元素的最长递增子序列······所以对于第
j个元素,对于它前面的元素可遍历,有遍历元素i,如果有  sub[ j ] >
sub[ i ],则有递推式:maxt[ j ] = max( maxt[ i ]+1 , maxt[ j ] ),

AC code:

#include<stdio.h>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
int main (void){
int a;
int i,j;
int sub[1005];
int maxt[1005],maxnumber=0;
for(i=0;i<1005;i++)
maxt[i] = 1;
cin>>a;
for(i=1;i<a+1;i++)
cin>>sub[i];
for(i=2;i<a+1;i++)
for(j=1;j<i;j++)
if(sub[i] > sub[j])
maxt[i] = max( maxt[j]+1 , maxt[i]);
for(i=1;i<=a;i++)
if(maxnumber < maxt[i])  maxnumber =  maxt[i];
printf("%d\n",maxnumber);
}


南洋理工:214

                                      单调递增子序列(二)

                                               时间限制:1000 ms  |  内存限制:65535 KB

                                                                     难度:4        描述:
给定一整型数列{a1,a2...,an}(0<n<=100000),找出单调递增最长子序列,并求出其长度。

如:1 9 10 5 11 2 13的最长单调递增子序列是1 9 10 11 13,长度为5。

输入:有多组测试数据(<=7)

每组测试数据的第一行是一个整数n表示序列中共有n个整数,随后的下一行里有n个整数,表示数列中的所有元素.每个整形数中间用空格间隔开(0<n<=100000)。

数据以EOF结束 。

输入数据保证合法(全为int型整数)!输出对于每组测试数据输出整形数列的最长递增子序列的长度,每个输出占一行。样例输入
7
1 9 10 5 11 2 13
2
2 -1

样例输出
5
1


解题分析:本题数据量为100000,故允许的时间复杂度为O(nlog(n)),所以不能用动态规划来解题,所以,我们得根据最长递增子序列的性质来解题。有1 5 2 8 4 7 3 0 6 9 数字序列,我们另外开一个数组存储最长子序列,则首先有1,5进入数组,同时遇到数子2,我们知道相对一1-5,明显1-2组合更有利,更有利于后面的数子继续加入最长连续子序列,所以抛弃5,选择2,不断维持最佳序列,重复此操作,(1,2,8)、(1,2,4)、(1,2,4,7)、(1,2,3,7)、(0,2,3,7)、(0,2,3,6)、(0,2,3,6,9)。故最后长度为5,中间不断通过二分查找来更新值。

AC code :

#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
int main (void){
int a;
int i;
while(scanf("%d",&a)!=EOF){
int length = 1;
int num[100005];
int ans[100005];
for(i=0;i<a;i++)
scanf("%d",&num[i]);
ans[0] = num[0];
for(i=1;i<a;i++){
int *pos;
//二分查找函数,查找大于或者等于查询值的下标
//只能用指针,否则编译错误
pos = lower_bound(ans,ans+length,num[i]);
if(pos - ans == length ) length++;
*pos = num[i];
}
printf("%d\n",length);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: