题目
Description
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
题目大意
什么是最长递增子序列呢?例如有一组数3 7 1 2 5,它的递增子序列有3 7 1 2 5 37 35 12 15 125。那么它的最长递增子序列的长度为3。即|125|=3;我们不要求这些子序列中的每个元素是相邻在一起的,只要保证他们递增即可。
思路
这道题和最大连续子序列和的思想一样。都是先固定一个元素,然后求以这个元素为末尾元素的最大递增子序列。比如上例的3 7 1 2 5,如果我们固定3为末尾 元素,那么最大递增子序列只能为3;如果7为末尾元素,那么它的最大递增子序列为37;如果1为末尾元素,那么最大递增子序列只能为1,因为它前面的3和7都比它大…以此类推。
那么我们就可以定义F(n)为以An为末尾元素的最长递增子序列的长度。那么由上面的分析我们知道,F(n)有两种情况。
- An前面的元素都比它大,或者An就是第一个元素,那么F(n)就等于1,也就是以An为末尾元素的最大递增子序列只有它本身。
- An前面存在比它大的元素,以An为末尾元素的最大递增子序列就等于An前面的最大递增子序列加上An,所以F(n) = Max|…Ai| + |Aj|,其中i<j&Ai<Aj
综上,F(n) = 1 或者 F(n) = F(i) + 1,其中Ai <An且i<n
有了这个公式,我们就可以写代码了。代码有三种写法:
- 朴素的递归算法
- 自顶而下的备忘录法
- 自底向上的递归算法
朴素的递归算法
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
const int MAXN = 1010;
int arr[MAXN];
int Func1(int n){
int answer;
if( n == 0){
answer = 1;
}
else{
answer = 1;
for(int i=0;i<n;i++){
if(arr[i] < arr[n]){
answer = max(answer,Func1(i)+1);
}
}
}
return answer;
}
int main()
{
int N;
scanf("%d",&N);
for(int i=0;i<N;i++){
scanf("%d",&arr[i]);
}
int maxNum = 0;
for(int i=0;i<N;i++){
maxNum = max(maxNum,Func1(i));
}
printf("%d\n",maxNum);
return 0;
}
自顶向下的备忘录法(递归+记忆化)
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
const int MAXN = 1010;
int arr[MAXN];
int Func1(int n){
int answer;
if( n == 0){
answer = 1;
}
else{
answer = 1;
for(int i=0;i<n;i++){
if(arr[i] < arr[n]){
answer = max(answer,Func1(i)+1);
}
}
}
return answer;
}
int memo[MAXN];
int Func2(int n){
int answer;
if(memo[n] != -1){
answer = memo[n];
}else{
if( n == 0){
answer = 1;
}
else{
answer = 1;
for(int i=0;i<n;i++){
if(arr[i] < arr[n]){
answer = max(answer,Func2(i)+1);
}
}
}
memo[n] = answer;
}
return answer;
}
int main()
{
int N;
scanf("%d",&N);
for(int i=0;i<N;i++){
scanf("%d",&arr[i]);
}
// int maxNum = 0;
// for(int i=0;i<N;i++){
// maxNum = max(maxNum,Func1(i));
// }
// printf("%d\n",maxNum);
fill(memo,memo+N,-1); //初始化
int maxNum = 0;
for(int i=0;i<N;i++){
maxNum = max(maxNum,Func2(i));
}
printf("%d\n",maxNum);
return 0;
}
自底向上的递推算法
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
const int MAXN = 1010;
int arr[MAXN];
int Func1(int n){
int answer;
if( n == 0){
answer = 1;
}
else{
answer = 1;
for(int i=0;i<n;i++){
if(arr[i] < arr[n]){
answer = max(answer,Func1(i)+1);
}
}
}
return answer;
}
int memo[MAXN];
int Func2(int n){
int answer;
if(memo[n] != -1){
answer = memo[n];
}else{
if( n == 0){
answer = 1;
}
else{
answer = 1;
for(int i=0;i<n;i++){
if(arr[i] < arr[n]){
answer = max(answer,Func2(i)+1);
}
}
}
memo[n] = answer;
}
return answer;
}
//用递推的方法算出每一个F(n)
int dp[MAXN];
void Func3(int n){
int answer;
for(int i=0;i<n;i++){
if(i == 0){
answer = 1;
}else{
answer = 1;
for(int j=0;j<i;j++){
if(arr[j] < arr[i]){
answer = max(answer,dp[j]+1);
}
}
}
dp[i] = answer;
}
return;
}
int main()
{
int N;
scanf("%d",&N);
for(int i=0;i<N;i++){
scanf("%d",&arr[i]);
}
// int maxNum = 0;
// for(int i=0;i<N;i++){
// maxNum = max(maxNum,Func1(i));
// }
// printf("%d\n",maxNum);
// fill(memo,memo+N,-1); //初始化
// int maxNum = 0;
// for(int i=0;i<N;i++){
// maxNum = max(maxNum,Func2(i));
// }
// printf("%d\n",maxNum);
fill(dp,dp+N,-1); //初始化
int maxNum = 0;
Func3(N);
for(int i=0;i<N;i++){
maxNum = max(maxNum,dp[i]);
}
printf("%d\n",maxNum);
return 0;
}