最长上升子序列

来源:互联网 发布:国家人工智能战略 编辑:程序博客网 时间:2024/06/04 23:29

示例题目:POJ2533
参考书籍:《挑战程序设计竞赛》

第一种方法:O(n^2)
dp[i]:以a[i]结尾的最长上升子序列的长度

  • 只包含a[i]的序列
  • 由a[j]追加a[i]得到(满足j< i并且a[j]< a[i])

状态转移方程:
dp[i]=max{dp[i],dp[j]+1}

#include<iostream>#include<cstring>#include<cmath>#include<algorithm>using namespace std;int a[1005];int dp[1005];int main(){    ios::sync_with_stdio(false);    int n;    while(cin>>n)    {        for(int i=1;i<=n;i++)        {            cin>>a[i];        }        memset(dp,0,sizeof(dp));        int res=0;        for(int i=1;i<=n;i++)        {            dp[i]=1;            for(int j=1;j<i;j++)            {                if(a[i]>a[j])                    dp[i]=max(dp[i],dp[j]+1);            }            res=max(dp[i],res);        }        cout<<res<<endl;    }    return 0;}

第二种方法:O(nlogn)
dp[i]:长度为i+1的上升子序列中末尾元素的最小值(不存在就是INF)
状态转移方程:
对数列从左往右扫一遍,对于当前扫到的元素a[j]
如果i=0或者dp[i-1]< a[j],就用dp[i]=min(dp[i],a[j])更新,
考虑到dp数列中除INF外是单调递增的,dp[i]的指针可由
lower_bound(dp,dp+n,a[j])得出。

#include<iostream>#include<cstring>#include<algorithm>using namespace std;const int INF=0x3f3f3f3f;int a[1005];int dp[1005];/// dp[i]表示长度为i+1的上升子序列中末尾元素的最小值/// 不存在就是INFint main(){    //int t[5]={1,2,4,4,5};    //cout<<lower_bound(t,t+5,3)-t<<endl;    ios::sync_with_stdio(false);    int n;    while(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];        }        cout<<lower_bound(dp,dp+n,INF)-dp<<endl;    }    return 0;}

按照白书上的理解

#include<iostream>#include<cstdio>#include<algorithm>using namespace std;const int INF=0x3f3f3f3f;int a[1005];int dp[1005];//dp[i]:以a[i]结尾的LIS的长度int g[1005];//g[k]=a[j]   (dp[j]=k&&j最小)///g[1]<=g[2]<=g[3]<=...<=g[n]  (if not exist g[i]=INF)///dp[i]=max(0,dp[j])+1   (j<i&&a[j]<a[i])int main(){    int n;    while(cin>>n)    {        for(int i=0;i<n;i++)            cin>>a[i];        fill(g,g+n+1,INF);        for(int i=0;i<n;i++)        {            //g[k']<a[i]<=g[k]   (k=k'+1)            int k=lower_bound(g+1,g+n+1,a[i])-g;            //g[k']=a[j']<a[i]   dp[j']=k'=k-1            //g[k]=a[j]>=a[i]            dp[i]=k;            //dp[i]=max(0,dp[j'])+1=k  (j'<i&&a[j']<a[i])            g[k]=a[i];        }        cout<<lower_bound(g+1,g+n+1,INF)-(g+1)<<endl;    }    return 0;}
1 0
原创粉丝点击