最长上升子序列的两种求法 POJ 2533

最长上升子序列一共有两种求法:

1.dp,也可以说的纯暴力吧。

dp[i]表示以a[i]为结尾的最长上升子序列的长度。

所以只要满足j<i且a[j]<a[i],则一定满足dp[j]=max(dp[j],dp[i]+1);

复杂度为n^2;

2.是在上述方法的优化,建一个dp数组。

dp[i]表示长度为i的上升子序列中末尾元素的最小值。

因为dp数组一定是有序的,这样每次插入元素的时候可以结合二分查找使效率更高。

复杂度为logn*n;

例题为poj 2533

1.第一种方法:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
const int maxn=1e3+5;
int n;
int a[maxn];
int dp[maxn];
int main()
{
	scanf("%d",&n);
	for (int i=1;i<=n;i++) scanf("%d",&a[i]);
	for (int i=1;i<=n;i++) dp[i]=1;
	int Max=1;
	for (int i=1;i<=n;i++)
	{
		for (int j=i+1;j<=n;j++)
		{
			if(a[i]<a[j]) dp[j]=max(dp[j],dp[i]+1);
			Max=max(dp[j],Max);
		}
	}	
	printf("%d\n",Max);
	return 0;
}

注意初始化Max=1。

2.第二种方法:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
const int maxn=1e3+5;
int n;
int a[maxn];
int dp[maxn];
int len;
int main()
{
	scanf("%d",&n);
	len=0;
	for (int i=1;i<=n;i++) scanf("%d",&a[i]);
	for (int i=1;i<=n;i++)
	{
		int loc=lower_bound(dp,dp+len,a[i])-dp;
		if(loc==len) dp[len++]=a[i];
		else 
		{
			dp[loc]=a[i];
		}
	}
	printf("%d\n",len);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41410799/article/details/88756530