ACM题解——动态规划系列——最长升序子序列

ACM题解——动态规划系列——最长升序子序列

题目描述

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

题意

给一串数字,寻找其最长的升序子序列,就是找其子序列,保证后面的数字始终大等其前面的数字,然后求这样的子序列中最长的那个。

题解

这个题目就是敌国导弹问题,数据很水,观察数据发现只有一次测试,而且测试序列长度不超过1000,因此可以考虑用O(n²)的算法实现。发现这个题目有些贪心属性,当判断当前数要最长非递减序列结尾的时候,其前面链接的一定是最长的非递减序列(因为后面能不能继续加数字只和当前这个数有关,和前面的数字都无关了,因此前面一定要选最长的),用dp[n]记录以当前值为结尾的最长非递减序列长度。外层循环表明以数字a[i]结尾,内层循环从0——i-1,观察链接哪个数字会让以i结尾的子序列达到最长,并实时更新最长的那一个的长度,最后两层循环结束,输出最长子序列长度值。

状态方程为  dp[i]=max(dp[j])+1  当然还有一个可以链接的条件必须是非递减序列,所以 a[j]>=a[i] 。

代码

#include<iostream>
using namespace std;
int main()
{
    int n=0;
    cin>>n;
    int *a=new int[n];
    int *dp=new int[n];
    for(int i=0;i<n;i++)
        cin>>a[i];
    int maxx=1;
    for(int i=0;i<n;i++)
    {
        dp[i]=1;                 //注意初始长度为1,只有当前结尾的一个数
        for(int j=0;j<i;j++)
        {
            if(a[j]<a[i] && dp[j]+1>dp[i])  //满足条件
                dp[i]=dp[j]+1;
            if(dp[i]>maxx)                  //记录更新最大值
                maxx=dp[i];
        }
    }
    cout<<maxx<<endl;
    return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值