51nod 2080 最长上升子序列

题目网址:http://class.51nod.com/Challenge/Problem.html#problemId=2080

一、题目描述

一个数列的最长上升子列,是指其所有递增的子列中最长的一个子列

给定一个长度为 n 的数列 an,求这个数列的最长上升子列的长度

例如对数列 1 7 2 8 3 4,这个数列的最长递增子数列是 1 2 3 4,长度为 4;次长的长度为 3, 包括 1 7 8、1 2 3 等。

输入描述

第一行一个正整数 n,表示数列元素个数,n<=1000

第二行 n 个正整数,从左到右给出数列的每一项

输出描述

一行一个正整数,表示最长上升子数列的长度

样例输入

8
5 1 6 8 2 4 5 10

样例输出

5

二、解题思路

我们定义dp[i]为以a[i]为结尾的最长上升子序列的长度。

a[i]结尾的上升子序列得满足:

1、j i(以a[j]为结尾的上升子序列)

2、a[j] a[i] 

3、看哪个最大

①以a[j]结尾的上升子序列结尾加上1(a[i])后得到的子序列。

②a[i]自己成立一个子序列

把最大的序列长度赋值到数组(sum)里存起来,最后看数组(sum)里的最大值

每个a[i]对应的序列长度最大值都存到sum[i]里去。 

时间复杂度是O(n2)。

三、AC代码

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

int main(){
    int n, a[1005], sum[100005]={0}, ans=0;
    cin >> n;
    for(int i = 1;i <= n;i++){
        cin >> a[i];
    }
    for(int i = 1;i <= n;i++){
        sum[i] = 1;//把每个数的长度初始值赋值为 1 
        for(int j = 1;j <= i-1;j++){//和a[i]前面所有的数作比较 
            if(a[j] < a[i]){//如果后面的数大于前面的数 
                //说明可以考虑要不要把a[i]这个数也加入前面的序列 
                //看是前面的序列再加上1(a[i])长
                //还是a[i]自己成立一个序列长 
                sum[i] = max(sum[i], sum[j]+1);
                //把更长的那个赋值到sum[i]里面去 
            }
        }
        ans = max(ans,sum[i]);//找出题目要求的最长的序列 
    }
    cout << ans << endl;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/elisa02/p/13374456.html