zoukankan      html  css  js  c++  java
  • 最长上升子序列问题

    1,坚持与否,成功与否,真还挺难说的。

    2,有一个长为n的数列a0,a1,....an-1。请求出这个序列中最长的上升子序列的长度,上升子序列指的是对于任意i<j都满足ai<aj的子序列。

    3,嗯还行我不会。奇奇怪怪用DP。LIS问题。。之前是不是还有另一个啥。。。

    4,

    #include<iostream>
    using namespace std;
    int n, a[1005];
    int dp[1005];
    int main(){
        cin>>n;
        for(int i=0;i<n;i++)   cin>>a[i];
        int res=0;
        for(int i=0;i<n;i++){
            dp[i]=1;
            for(int j=0;j<i;j++){
                if(a[j]<a[i]){
                    dp[i]=max(dp[i],dp[j]+1);
                }
                res=max(res,dp[i]);
            }
        }
        cout<<res<<endl;
    } 

    5,奇奇怪怪,res咋能递增呢。(res递增你是没看懂人家dp的定义啊)

    额自动保存个屁啊。没有,,

    6,开始费大和费小。

    人家先是定义dp[i[为以ai为末尾的最长上升子序列的长度。

    不久之前那个开门见山么。那直接背算了。这样死记硬背感觉不太好。确实不太好,但是也没啥太好的方法。

    dp就背定义和递推式呗。。

    dp[i]=max{1,dp[j]+1|j<i且aj<ai};

    那么费大就到此为止。

    我们来费小。

    倒是推了一遍明白了不少道理。但是到底是个什么东西呢?

    有点像堆积木??递推??

    堆积木吧?倒不如说是附加。

    7,就算改了

    #include<iostream>
    using namespace std;
    int n,a[1005],dp[1005];
    int main(){
        cin>>n;
        for(int i=0;i<n;i++) cin>>a[i];
        int res=0;
        for(int i=0;i+1<n+1;i++){
            dp[i]=1;
            for(int j=0;j<i;j++){
                if(a[j]<a[i])
                {
                    dp[i]=max(dp[i],dp[j]+1);
                }
                res=max(res,dp[i]);
            }
        }
        cout<<res<<endl;
    }

    呵呵呵俄呵呵呵。

    8,第二种DP。

    还用一个fill函数的应用。在#include<algorithm>中,

    先来介绍下lower_bound函数。书上解释的怪那啥的。

    #include <algorithm>
    #include <iostream>
    using namespace std;
    int main()
    {
        int a[]={1,2,3,4,5,7,8,9};
        printf("%d",lower_bound(a,a+8,6)-a); 
        
     return 0;    
    } 
    输出:5

    就是返回大于等于key值得第一个位置。

    顺便..

     函数upper_bound() 功能:函数upper_bound()返回的在前闭后开区间查找的关键字的上界,返回大于val的第一个元素位置 

    虽然有点玄幻但是还是挺容易懂得。

    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int INF=1005;
    int n,dp[1005],a[1005];
    int main(){
        cin>>n;
        for(int i=0;i<n;i++) cin>>a[i];
        fill(dp,dp+n,INF);
        for(int i=0;i<n;i++)
        {
            *lower_bound(dp,dp+n,a[i])=a[i];
        }
        int ans=lower_bound(dp,dp+n,INF)-dp;
        cout<<ans<<endl;
    }

    让我们来费大费小,这费大挺难费得,说实话,

    来,我们打一遍,前面我们利用DP求取针对最末位得元素得最长得子序列。如果子序列的长度相同,那么最末尾的元素较小的在之后回会更加有优势,所以我们再反过来用DP针对相同长度情况下最小的末尾元素进行求解。

    dp[i]:=长度为i+1的上升子序列中末尾元素的最小值,(不存在的话就是INF),联系一下情况好像是这样。

    让我们来看看如何用DP来更新这个数组。

    最开始全部dp[i]的值都初始化为INF。然后由前到后逐个考虑数组的元素,

    对于每个aj,如果i=0或者dp[i-1]<aj的话,就用dp[i]=min(dp[i],aj)进行更新。

    这种抽象的东西你得把它弄清,然而你该如何把这个东西给弄清。

    模拟呗,我先把代码细节模拟一下,再去带文字上的东西,

    lower_bound就隐含着一个要比较的过程。

    我觉得现在就看你能用什么手段把这个东西给弄一弄。。除了模拟???

    所以这里放个坑算了,关于文字的推导不对。。你看看想个方法吧。

    我很惭愧,改不出来啥。

    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int INF=1005;
    int n,dp[1005],a[1005];
    int main(){
        cin>>n;
        for(int i=0;i<n;i++) cin>>a[i];
        fill(dp,dp+n+1,INF);
        for(int i=0;i<n;i++)
        {
            *lower_bound(dp,dp+n+1,a[i])=a[i];
        }
        int ans=lower_bound(dp,dp+n+1,INF)-dp;     
        cout<<ans<<endl;
    }

    加个1就当改了哦

  • 相关阅读:
    新浪微盘又是一个给力的产品啊,
    InfoQ: 百度数据库架构演变与设计
    列式数据库——Sybase IQ
    MapR初体验 淘宝共享数据平台 tbdata.org
    IBM正式发布新一代zEnterprise大型机(组图) 大型机,IBM,BladeCenter,美国,纽约 TechWeb News
    1TB is equal to the number of how many GB? 1PB equal to is equal to the number of TB? 1EB PB? | PCfault.com
    Cassandra vs HBase | WhyNosql
    The Hadoop Community Effect
    雅虎剥离开源软件平台 Hadoop ,与风投新建 Hortonworks 公司 品味雅虎
    RowOriented Database 、ColumnOriented Database 、KeyValue Store Database 、DocumentOriented Database
  • 原文地址:https://www.cnblogs.com/beiyueya/p/12170999.html
Copyright © 2011-2022 走看看