POJ 2533 : (DP,最长上升子序列LIS)

题目链接:http://poj.org/problem?id=2533

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

题意:

   求一数列最长上升子序列。


思路:

扫描二维码关注公众号,回复: 2206124 查看本文章

套用求最长上升子序列模板,没错这就是模板题

咳咳~,其实学过点dp的应该能想出暴力解法:[1,n]依次找每一个数i,然后再往这个数前面依次遍历[1,i-1],发现比i小的数j且dp[j]+1>dp[i]的话更新dp[i]=dp[j]+1,满足最长,满足递增,最后找出dp[]中的最大值。时间复杂度最坏是n^2;

所以一般会采用二分法来降低时间复杂度,变成nlogn,而且二分法还可以记录一个子序列哦。二分法会开一个数组记录子序列,这里用b[]表示,原序列用a[]表示

先用b[1]=a[1],记录开头,后遍历一次[2,n]来更新b[],以及b的长度len

当a[i]>b[len](即比b中最大的还要大时),坚持“不要白不要的原则",使得b[++len]=a[i],

当不满足时,就要用二分法把a[i]插入到b[]中去替换掉一个元素(因为a[i]<=b[],且b[]一直为升序状态),

最终得到的len就是子序列长度

证明的话有个好的博客:http://www.cnblogs.com/GodA/p/5180560.html

AC代码:(暴力)

Time 32ms
Memory 340kB
Length 487

#include <cstdio>
#include <algorithm>
using namespace std;
int a[10005],dp[10005];
int main()
{
    int n,ans;
    scanf("%d",&n);
    ans=1;
    for( int i=0; i<n; i++ )
    scanf("%d",&a[i]);
    for( int i=0; i<n; i++ )
    {
        dp[i] = 1;
        for( int j=0; j<i; j++ )
        {
            if( a[j]<a[i] && dp[i]<dp[j]+1 )
            {
                dp[i] = dp[j] + 1;
            }
        }
        ans = max(ans,dp[i]);
    }
    printf("%d\n",ans);

    return 0;
}


AC代码:(二分)

Time 16ms
Memory 332kb
Length

495
#include <cstdio>
#include <algorithm>
using namespace std;
int a[10005],b[10005];
int main()
{
    int n;
    scanf("%d",&n);
    for( int i=1; i<=n; i++ )
    {
        scanf("%d",&a[i]);
    }
    int len = 1;
    b[1] = a[1] ;
    for( int i=1; i<=n; i++ )
    {
        if( b[len]<a[i] )
        {
            b[++len]=a[i];
        }
        else
        {
            int k = lower_bound(b+1,b+len,a[i])-b;
            b[k] = a[i];
        }
    }
    printf("%d\n",len);
    return 0;
}




猜你喜欢

转载自blog.csdn.net/qq_40764917/article/details/81037525