最长上升子序列(LIS)

题目:

LIS (Longest Increasing Subsequence)为最长上升子序列:
给定n个元素的数列,求最长的上升子序列长度(LIS)。

一个数的序列ai,当a1 < a2 < … < aS的时候,我们称这个序列是上升的。
比如,对于序列(1, 7, 3, 5, 9, 4, 8),有它的一些上升子序列,如(1, 7), (3, 4, 8)等等。这些子序列中最长的长度是4,比如子序列(1, 3, 5, 8).
对于给定的序列,求出最长上升子序列的长度。

输入

输入包含两行,第一行只有一个整数N(1 <= N <= 1000),表示数列的长度。第二行有N个自然数ai,0 <= ai <= 1000,两个数之间用空格隔开。

输出

输出只有一行,包含一个整数,表示最长上升子序列的长度。

1.暴力搜索

#include<iostream>
#include<cstdio>
using namespace std;
int n,a[1001];

int dfs(int i)
{
    int s=0;
    for(int j=i+1;j<=n;j++)
      if(a[i]<a[j]) s=max(s,dfs(j));
    s++;
    return s;
}
int main()
{
    int ans=0;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
     } 
    for(int i=1;i<=n;i++)
    {
        ans=max(ans,dfs(i));
    }
    cout<<ans<<endl;
}

2.倒序递推求f[i]

#include<iostream>
#include<cstdio>
using namespace std;
int n,a[1001],f[1001];

int main()
{
    int ans=0;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
     } 
     f[n]=1;
    for(int i=n-1;i>=1;i--)
    {
        f[i]=0;
        for(int j=1+i;j<=n;j++)
          if(a[i]<a[j]) f[i]=max(f[i],f[j]);
        f[i]++;
    }

    for(int i=1;i<=n;i++)
      ans=max(ans,f[i]);
    cout<<ans<<endl;
    return 0;
}

3.记忆化搜索

#include<iostream>
#include<cstdio>
using namespace std;
int n,a[1001],f[1001];

int dfs(int i)
{
    if(f[i]>0) return f[i];
    f[i]=0;
    int s=0;
    for(int j=i+1;j<=n;j++)
      if(a[i]<a[j]) f[i]=max(f[i],dfs(j));
    f[i]++;
    return f[i];
}
int main()
{
    int ans=0;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
     } 
    for(int i=1;i<=n;i++)
    {
        ans=max(ans,dfs(i));
    }
    cout<<ans<<endl;
}

 

posted @ 2022-09-25 19:48  为么要取名字  阅读(397)  评论(0编辑  收藏  举报