【POJ 2533】Longest Ordered Subsequence(dp求最长增序列的长度)


点击打开题目


Longest Ordered Subsequence
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 54151 Accepted: 24214

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.

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

Source

Northeastern Europe 2002, Far-Eastern Subregion

题意:

 鹏神意外得到了神灯。

  神灯中冒出了灯神,灯神说道:“我将给你一个有序的数列,你可以在保证原有顺序不变的前提下,挑出任意多的数。如果你挑出的数字是严格升序的,那么这段数字的个数就是你女朋友的个数。”

  “妈的智障。”鹏神骂道。

  但是鹏神还是希望自己能有尽可能多的女朋友。所以他求救于你,希望你能帮他算出他最多能有多少女朋友。

Input

  输入包含多组数据。

  第一行是以为整数N,表示灯神给出的数列的长度。(1≤N≤1000)

  第二行包含N个整数,即是灯神给出的序列。

Output

  对于每组输入数据,请输出最终答案,即鹏神最多可以得到的女朋友个数。


题意:输出最长递增子序列的长度
思路:直接裸LIS,第一次使用,使用两种方法

f(i)表示:从左向右扫描过来直到以a[i]元素结尾的序列,可获得的最长上升子序列的长度,且子序列包含a[i]元素(1<=i<=n)。

f(i)是从f(1),f(2), ……到f(i-1)中找最大的一个值,再加1。或者就是1。
这主要得看a[i]这个元素能否加入到之前已经获得的最长上升子序列当中去,
如果能加入,是之前已获得的最长上升子序列长度加一;
如果不能加入,就开始一个新的上升子序列,长度为1。
最后,所要求的整个序列的最长上升子序列长度为max{f(i): 1<=i<=n}

f(i)的递推公式如下:
1)f(i)=1  当i=1;
2)f(i)=max{f(j)+1}  当a[i]>a[j],j大于等于1且小于i,i>1;
3)f(i)=1  当对任意j,(j大于等于1且小于i),都有a[i]<=a[j];

例子,对于序列:4  2  6  3  1  5  2
i   = 1  2  3  4  5  6  7
a[i]= 4  2  6  3  1  5  2
f(i)= 1  1  2  2  1  3  2
这里max{f(i)}=3为原问题所求的最长上升子序列的长度。
第一种代码:(复杂度为o(n^2))

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define INF 0x3f3f3f3f
using namespace std;

const int MAX=1e3+10;
int dp[MAX];
int num[MAX];

int main(){
	int n;
	while(cin>>n){
	//	memset(dp,0,sizeof(dp));
		for(int i=0;i<n;i++){
			scanf("%d",&num[i]);
			dp[i]=1;
		}
		int ans=1;
		int temp;
		for(int i=1;i<n;i++){
			temp=0;
			for(int j=0;j<i;j++){
				if(num[i]>num[j] && dp[j]>temp)
				temp=dp[j];
			}
			dp[i]=temp+1;
			ans=max(dp[i],ans);
		}
		cout<<ans<<endl;
	}
	return 0;
}

第二种:复杂度为O(nlogn)

利用二分

#include "stdio.h"
#include "math.h"
 
int a[1000][1000];
 
static int c[1000];
 
int Compare_num(int a,int b)
{
    if(a<b)
        return 1;
    else
        return 0;
}
 
int Longest(int list[][1000],int j,int k)
{
    int i;
    int t=0;
    for(i=1;i<=k;i++)
    {
        if(Compare_num(c[t],list[j][i]))
        {
            t++;
            c[t]=list[j][i];
        }
        else
        {
            int low,high;
            low=0;high=t;
            int mid=(high+low)/2;
            while(high-low>1)
                {
                    if(Compare_num(list[j][i],c[mid])) 
                        high=mid; 
                    else
                        low=mid;
                    mid=(low+high)/2;
                }
                c[high]=list[j][i];
        }
    }
    return t;
}
 
int main()
{   
    int i=0;
    int j,k,b;
    b=0;
    c[1]=1;
    scanf("%d",&a[i][0]);
    while( a[i][0]!= 0 )
    {
        for (j=1; j<=a[i][0] ; j++)
            scanf("%d",&a[i][j]);
        i++;
        scanf("%d",&a[i][0]);
    }
    for(j=0;j<i;j++)
    {       b=0;
            c[0]=-1;
            b=Longest(a,j,a[j][0]);     
            printf("%d\n",b);
    }
    return 1;
}







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值