#546. 最长不下降序列(LIS)

给定一个整数序列,文章描述了如何找出其中最长的不下降子序列,提供了暴力解法和动态规划解决方案,并给出了样例输入和输出。动态规划方法能更有效地找到答案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Background

Special for beginners, ^_^

Description

设有由 nn 个不相同的整数组成的数列,记为:b_1,b_2,\dots,b_nb1,b2,…,bn 且 b_i\neq b_j (i\neq j)bi=bj(i=j),若存在 i_1<i_2<i_3<\dots < i_ei1<i2<i3<⋯<ie 且有 b_{i_1}<b_{i_2}<\dots <b_{i_e}bi1<bi2<⋯<bie 则称为长度为 ee 的不下降序列。

当原数列出之后,求出最长的不下降序列。

例如 13,7,9,16,38,24,37,18,44,19,21,22,63,15。

例中 13,16,18,19,21,22,63 就是一个长度为 7 的不下降序列,同时也有 7,9,16,18,19,21,22,63 长度为 8 的不下降序列。

Format

Input

输入一行若干个整数,个数小于 100,取值小于 50000。

Output

输出两行。

第一行输出一个整数 e。

第二行输出 e 个整数,为最长不下降序列。

Samples

输入数据 1

300 250 275 252 200 138 245

Copy

输出数据 1

2
250 275 

Copy

Limitation

1s, 1024KiB for each test case.

/*
这是暴戾做法,时间较慢
#include <bits/stdc++.h>
using namespace std;

const int N=107;

int b[N][5];

int main(){
    int n=0;
    int l,k;
    while(cin>>b[++n][1]){
        b[n][2]=1;
        b[n][3]=0;
    }
    n--;
    for(int i=1;i<=n;i++){
        cin>>b[i][1];
        b[i][2]=1;
        b[i][3]=0;
    }
    for(int i=n-1;i>=1;i--){
        l=0;
        k=0;
        for(int j=i+1;j<=n;j++){
            if((b[j][1]>b[i][1])&&(b[j][2]>l)){
                l=b[j][2];
                k=j;
            }
            if(l>0){
                b[i][2]=l+1;
                b[i][3]=k;
            }
        }
    }
    k=1;
    for(int j=1;j<=n;j++){
        if(b[j][2]>b[k][2])k=j;
    }
    cout<<b[k][2]<<endl;
    while(k){
        cout<<b[k][1]<<" ";
        k=b[k][3];
    }
    return 0;
}
下面是动态规划,比较快
*/
#include<iostream>
using namespace std;

const int N=1007;

int dp[N];

int a[N];

int num[N];

int h,d,c;

int w=1;

int MXN;

void print(int a){
    if(!dp[a])return;
    print(dp[a]);
    cout<<num[a]<<" ";
}

int main() {
    while(cin>>num[++h]);
    for(int i=1;i<=h;++i){
        a[i]=1;
        MXN=0;
        for(int j=1;j<i;++j){
            if(a[j]>MXN&&num[j]<num[i]) {
                MXN=a[j];
                a[i]=a[j]+1;
                c=j;
            }
        }
        dp[i]=c;
        if(a[i]>d){
            d=a[i];
            w=i;
        }
    }
    cout<<d<<endl;
    print(w);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值