最长上升子序列(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; }