zoukankan      html  css  js  c++  java
  • 也谈最长不降子序列的长度

    题目是一本通网站(ybt.ssoier.cn:8088)中1259:【例9.3】求最长不下降序列

    【题目描述】

    设有由n(1n200)n(1≤n≤200)个不相同的整数组成的数列,

    记为:b(1)b(2)b(n)b(1)、b(2)、……、b(n)且b(i)b(j)(ij)b(i)≠b(j)(i≠j),

    若存在i1<i2<i3<<iei1<i2<i3<…<ie且有b(i1)<b(i2)<<b(ie)b(i1)<b(i2)<…<b(ie)

    则称为长度为e的不下降序列。程序要求,当原数列出之后,求出最长的不下降序列。

    例如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的不下降序列。 

    【输入】

    第一行为n,第二行为用空格隔开的n个整数。

    【输出】

    第一行为输出最大个数max(形式见样例);

    第二行为max个整数形成的不下降序列,答案可能不唯一,输出一种就可以了,本题进行特殊评测。

    【输入样例】

    14

    13 7 9 16 38 24 37 18 44 19 21 22 63 15

    【输出样例】

    max=8
    7 9 16 18 19 21 22 63

    其实这个题很多的网文都说到了,我也看了好久才看懂,然后把我的理解发
    出来大家下,希望还没看懂别的博文的朋友这次能让你懂。
    在众多的网文中,
    https://blog.csdn.net/sdz20172133/article/details/79265834
    这位兄弟pxlsdz说的算比较详细的了,感谢你。

    输入的序号

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    输入的值

    13

    7

    9

    16

    38

    24

    37

    18

    44

    19

    21

    22

    63

    15

    不降序列的长度

    1

    1

    2

    3

    4

    4

    5

    4

    6

    5

    6

    7

    8

    3






    我们可以用数组来记录不降序列的长度
    一个一个数字的解释吧。第一个数13,
    当然长度是1,就一个数嘛。第2个数7的长度也是1,共就两个数,7比13小,不
    能形成长度为2的不降序列,就是1了。实际上这个时候可以理解为有两个序列了,
    一个是13开头,一个是7开头。第3个数9,它可以接在7后面,不能接在13后面,
    当然没必须再开一个新序列(不是最长嘛),所以是2。第4个数16可以接在13的
    后面,那13的长度可以为2,但如果16接在9的后面,长度那形成的序列是7,9,
    16,长度为3,显然应接在9后面,第5个数38接在16的后面,长度为4。这个时候
    有一个长度为4的序列7,9,16,38。第6个数24,它不能接在38后面,但可以
    接在16的后面,也就是如果要把24加入一个最长序列的话,那只是不要38了,
    这将形成一个序列7,9,16,24,长度为4。第7个数37当然可以接在24的后面,
    形成一个度为5的序列。(如果第7个数不是37,而是38,那39可以接在38后面,
    也可以接在24的后面,那长度都一样)。第8个数18来了,它只能接在16的后面,
    形成一个长度为4的序列。第9个数可以接在38、24、37、18的任何一个数的后
    面,那接在谁的后面能获得最大长度呢?当然是37了,可以得长7,9,16,24,
    37,44的序列,长度相比而言应该是最长的了。所以44的长度是6。接着19,21,
    22当然顺次接到18的后面就好,所以长度分别为5,6,7。63应该可以接到44的
    后面,长度为7,也可以接到22的后面,长度为8,那当然得往大的方面走了,所
    以63的长度定为8。最后一个15只能接到9的后面,长度自然是3。每一个数的序
    列长度实际上是把它与前面的数比较,找到比它小对应长度又最大的数就好(从
    后面往前面找,长度也就是找数的升序+1)打擂记录最大长度就得到答案了。如
    果要找出最长子序列,那就需要记录每一个数的前一个数了,当然记序号也可。
    //求最长不降子序列长度,一本通网站1259题 
    #include<iostream>
    using namespace std;
    int a[201],b[201],c[201],mx=1,mxn;
    void pr(int x)
    {
        if(b[x]>1)pr(c[x]);
        cout<<a[x]<<' ';
        return;
    }
    int main(){
        int n;
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
            b[i]=1;
        }
        mxn=n;//如果最长不降子序列只有一个元素就输出最后一个元素 
        for(int i=2;i<=n;i++)
            for(int j=i-1;j>=1;j--)
                if(a[i]>=a[j]&&b[j]>=b[i])
                {
                    b[i]=b[j]+1;
                    if(mx<=b[i])mx=b[i],mxn=i;
                    c[i]=j;
                }
        cout<<"max="<<mx<<endl;
        if(mx>1)pr(c[mxn]);//本可以直接pr(mxn),但最后会多一个空格 
        cout<<a[mxn];//为避免最后多一个空格,最后一个元素单独输出 
        return 0;
    }
    View Code
    这种方法的时间复杂度是O(n^2)级,如果n较大,容易超时,可以用二分法搜索回以优化,可以把时间复杂度做到O(nlogn),现提供“之江学院石”的朋友的代码
    #include<bits/stdc++.h>
    using namespace std;
    int a[201], b[201], mx = 1, mxn, n;
    int main()
    {
        cin >> n >> a[0];
        b[0] = a[0];
        for(int i = 1; i < n; i++)
        {
            cin >> a[i];
            int j = upper_bound(b, b+mx, a[i]) - b;
            if(j == mx)
                mx++, mxn = i;
            b[j] = a[i];
        }
        for(int i = mx-2, j = mxn-1; i >= 0; i--)
        {
            for(; a[j] < b[i] || a[j] > b[i+1]; j--);
            b[i] = a[j--];
        }
        printf("max=%d
    ", mx);
        for(int i = 0; i < mx; i++)
            printf("%d%c", b[i], i == mx - 1 ? '
    ' : ' ');
    }
    View Code
    
    
    
    
    
    如有不妥之处,请指教!
     
  • 相关阅读:
    spring 源码解析(三)
    spring 源码解析(三)
    spring 源码解析(三)
    spring 源码解析(三) 容器的实现
    spring 源码解析(二) 3.修改编译生成,生成自定义版本。
    spring 源码解析(二) 1.开发环境,环境的搭建。
    思维-J
    思维-Ayoub's function
    图-D
    思维-Codeforces 1294D
  • 原文地址:https://www.cnblogs.com/wendcn/p/10473474.html
Copyright © 2011-2022 走看看