最长上升子序列

来源:互联网 发布:js调用手机相册插件 编辑:程序博客网 时间:2024/04/30 18:14
题意:

1759:最长上升子序列

总时间限制:
2000ms
内存限制:
65536kB
描述
一个数的序列bi,当b1 < b2 < ... <bS的时候,我们称这个序列是上升的。对于给定的一个序列(a1,a2, ...,aN),我们可以得到一些上升的子序列(ai1,ai2, ...,aiK),这里1 <=i1 < i2 < ... <iK <= N。比如,对于序列(1, 7, 3, 5, 9, 4, 8),有它的一些上升子序列,如(1, 7), (3, 4, 8)等等。这些子序列中最长的长度是4,比如子序列(1, 3, 5, 8).

你的任务,就是对于给定的序列,求出最长上升子序列的长度。
输入
输入的第一行是序列的长度N (1 <= N <= 1000)。第二行给出序列中的N个整数,这些整数的取值范围都在0到10000。
输出
最长上升子序列的长度。
样例输入
71 7 3 5 9 4 8
样例输出
4


最长上升子序列是DP中很基础的一个模型,但却很重要,因为在很多以后的题中都要用到他来解决问题,就像01背包一样,用来理解DP是非常不错的。


解题思路:

对于本题来说一共有两种常见的方法可解,一种是O(n^n)的,还有一种是O(nlogn)的解法。两种解法都是以前i个序列为阶段,以每个阶段的最长上升子序列的个数为状态,并且每次判断第i阶段中是否有新的子序列能使f【i】更新。f【i】为第i阶段的最大上升子序列的个数。


好先来说一下n^n的算法吧。每次枚举前i个数,并枚举前i个数中的每个数,以此来检查更新。

#include<iostream>#include<cstdio>using namespace std;int n;int a[1002];int f[1002];int main(){    scanf("%d",&n);    for(int i = 1;i <= n; i++){        scanf("%d",&a[i]);        f[i] = 1;//初始化每个数都为一个子序列,且长度为一。    }    for(int i = 2;i <= n; i++){        for(int j = 1;j < i; j++){            if(a[j] < a[i]){//判断前i个数中假如有第j个数比他小,就相当于前j个数构成的最大上升子序列和第i个数可以构成一个更大的上升子序列。                f[i] = max(f[i],f[j]+1);//判断新构成的上升子序列是否比当前的大,大的更新。            }        }    }    int ans = -9999999;    for(int i = 1;i <= n; i++)ans = max(ans,f[i]);//找出最大的上升子序列。    printf("%d",ans);}

而nlogn得算法其实就是将枚举前i个数的每个数换成了当前最大上升子序列中,他a【i】可以排在哪里。

#include<iostream>#include<cstdio>using namespace std;int n;int a[1002];int c[1002];int find(int left,int right,int key){    while(left != right){        int mid = (left+right)/2;        if(key <= c[mid])right = mid;        else left = mid+1;    }    return left;}int main(){    scanf("%d",&n);    for(int i = 1;i <= n; i++)scanf("%d",&a[i]);    c[0] = -9999999;    int len = 0;    int j = 0;    for(int i = 1;i <= n; i++){        if(a[i] > c[len])j = ++len;//c【len】为当前最大上升子序列上升中最大的一个数,如果a【i】任然比他大,则可构成新的最大上升子序列。        else j = find(1,len,a[i]);//如果a【i】比他小就判断在当前最大上升子序列中,能排在哪里。        c[j] = a[i];//跟新最大上升子序列,可以在后面加长,也可以使前面的跟小,如果前面的数越小,则后面的数跟容易比他大。    }    printf("%d\n",len);    //for(int i = 1;i <= len; i++)printf("%d ",c[i]);}



0 0
原创粉丝点击