DP算法解最长上升子序列问题,这里介绍两种算法O(n*n)和O(nlgn)
以poj 2533为例。
O(n*n):
令a[i]为序列的第i个元素,d[i]为以元素a[i]结尾的LIS长度
当0<j<=i-1时:
if(a[j] >= a[i]) then d[i] = 1;
if(a[j] < a[i]) then d[i] = max(d[i],d[j] + 1)
#include<cstdio> #include<iostream> #define N 1002 using namespace std; int a[N],l[N]; int main(void) { int n; scanf("%d",&n); int i,j; for(i=1;i<=n;i++) scanf("%d",&a[i]); int ans = 0; for(i=1;i<=n;i++) { l[i] = 1; for(j=1;j<=i-1;j++) { if(a[j] < a[i] && l[i] < l[j] + 1) l[i] = l[j] + 1; } ans = (l[i] > ans ? l[i] : ans); } cout<<ans<<endl; return 0; }
令a[i]为序列的第i个元素,s[n]为最长子序列。
开始时s[1] = a[1],若a[2] > s[1],那么 s[2] = a[2],否则 s[1] = a[2] ......
这一步一个lower_bound()函数就解决啦
#include<cstdio> #include<iostream> #include<string.h> #include<stdlib.h> #include<algorithm> #define N 1002 using namespace std; int a[N],s[N],d[N]; int main(void) { int n; scanf("%d",&n); int i,j; for(i=0;i<n;i++) scanf("%d",&a[i]); for(i=1;i<=n;i++) s[i] = 1000000000; int ans = 0; for(i=0;i<n;i++) { j = lower_bound(s+1,s+n+1,a[i]) - s; d[i] = j; s[j] = a[i]; ans = max(ans,d[i]); } cout<<ans<<endl; return 0; }