POJ 2553 最长上升子序列

http://poj.org/problem?id=2533

A numeric sequence of ai is ordered if a1 < a2 < ... < aN. Let the subsequence of the given numeric sequence ( a1, a2, ..., aN) be any sequence ( ai1, ai2, ..., aiK), where 1 <= i1 < i2 < ... < iK <= N. For example, sequence (1, 7, 3, 5, 9, 4, 8) has ordered subsequences, e. g., (1, 7), (3, 4, 8) and many others. All longest ordered subsequences are of length 4, e. g., (1, 3, 5, 8).

Your program, when given the numeric sequence, must find the length of its longest ordered subsequence.

Input

The first line of input file contains the length of sequence N. The second line contains the elements of sequence - N integers in the range from 0 to 10000 each, separated by spaces. 1 <= N <= 1000

Output

Output file must contain a single integer - the length of the longest ordered subsequence of the given sequence.

Sample Input

7
1 7 3 5 9 4 8

Sample Output

4

题目大意:求最长上升子序列的长度。

方法一:

思路:dp[i]表示以a[i]结尾的上升子序列的长度。外层循环i从1到n遍历原序列,内层循环j从1到i,当a[j]

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define INF 0x3f3f3f3f
#define EPS 1e-10
typedef long long ll;
typedef unsigned long long ull;
using namespace std;

int dp[1005];
int a[1005];

int main()
{
	int n;
	scanf("%d",&n);
	for(int i=0;i

方法二:

思路:因为求的是最长上升子序列,因此我们考虑维护一个单调增的数组low,初始化low[0]=a[0],然后从1到n-1遍历原序列,若a[i]大于当前low数组的最后一个值,那么把a[i]直接接到后面;反之,我们在low数组中二分查找到第一个大于等于a[i]的元素,(因为这里是上升子序列 而不是非减子序列)并用a[i]替换掉这个元素。这里用到的是贪心的思想,因为你想找一个最长的上升子序列,那么靠前的元素越小越好,而且将后面的元素插入、替换到low数组中,并没有什么问题,因为长度并没有发生变化,这样做只是为了搜寻可能的最优解。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define INF 0x3f3f3f3f
#define EPS 1e-10
typedef long long ll;
typedef unsigned long long ull;
using namespace std;

int low[1005];
int a[1005];

int main()
{
	int n;
	scanf("%d",&n);
	for(int i=0;ilow[k])//a[i]大于当前low数组中最大的 可以直接放到后面
			low[++k]=a[i];
		else	//否则在low数组找到第一个大于或等于a[i]的替换 因为这里是严格上升的 否则可用upper_bound
			low[lower_bound(low,low+k+1,a[i])-low]=a[i];
	}
	printf("%d\n",k+1);
	return 0;
}

方法三:

思路:树状数组优化。朴素的dp方程是:dp[i]=max(dp[j]+1,dp[i]),(1<=j记录第i个元素的下标,对序列a按照权值从小到大排序(这样就满足了a[j]),那么正向迭代的时候,只需要考虑下标的问题,即对于a[i],我们只需要知道以a[j]结尾且jtree[i]=max(dp[a[i]],dp[a[i-1]],dp[a[i-2]],………dp[a[i-lowbit(i)+1]])+1即可。反着来也可以,即对序列a的权重做离散化处理(避免越界),此时正向迭代满足了i

最长上升:

#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;


struct node
{
    int v,id;
    bool operator <(const node &a)const
    {
        return v

最长非降: 

#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;


struct node
{
    int v,id;
    bool operator <(const node &a)const
    {
        return v

 

你可能感兴趣的:(dp,动态规划)