最长上升子序列
题目描述

题目解析
本题介绍最长上升子序列的一般解法,当数据量不大时用这种解法。 在此之前,先区分一下子数组和子序列,子数组需要是连续的,而子序列可以是间断的。
-
状态表示
dp[i]表示以i结尾的所有子序列中,最长的上升子序列长度。 -
状态转移方程 分两种情况推导: 一、当序列长度为 1 时,因为
dp[i]自己本身就是一个子序列,所以dp[i]的最小取值可能是 1(比如总序列是一个递减序列的话,那么每个dp[i]的取值都会是 1)。 二、当序列长度大于 1 时,如果第i个格子前面的所有格子中有比第i个格子小的格子,记为j,那么第i个格子就可以挂在j格子后面组成一个序列,序列长度就是dp[j] + 1。因为我们要求最长上升子序列,所以需要遍历dp数组中从 1 到i-1的所有值,找出所有a[j]小于a[i]的格子,从中选出dp[j] + 1的最大值,该值为dp[i]的取值。

所以状态转移方程如下图所示:

-
初始化 因为我们没遍历到一个格子都会先把
dp[i]置为 1,所以dp数组不用初始化,用默认值 0 即可。 -
填表顺序 从左往右。
-
输出结果 结果为
dp数组从 1 到n的所有取值的最大值。
代码
#include <iostream>
#include <algorithm>
using namespace std;
N = ;
n;
a[N], dp[N];
{
cin >> n;
( i = ; i <= n; i++) {
cin >> a[i];
}
ret = ;
( i = ; i <= n; i++) {
dp[i] = ;
( j = ; j < i; j++) {
(a[j] < a[i]) {
dp[i] = (dp[i], dp[j] + );
}
}
ret = (ret, dp[i]);
}
cout << ret << endl;
;
}







