现在的位置: 首页 > 综合 > 正文

浅析最长上升子序列问题

2019年08月14日 ⁄ 综合 ⁄ 共 1020字 ⁄ 字号 评论关闭

    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;
}

       O(nlgn):

           令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;
}

抱歉!评论已关闭.