题目描述
https://www.acwing.com/activity/content/problem/content/1003/1
算法思路
- 最长上升子序列问题的状态表示f[i]的含义为:以第i个数字结尾的所有最长上升子序列集合中,子序列长度的最大值
- 集合的划分: 通过最长上升子序列的定义就能知道,f[i]一定包含了第i个元素,那么如何进行集合的划分呢?
- 考虑第f[i]的前一个数是序列中的哪一个数,假如是第序列中的第j个数,当确定了f[i]前一个数是哪一个数之后,就知道f[i] = f[j]+1。
- 在代码实现的时候,为了找到f[i]的前一个数,只能依次遍历前面i个数,直到找到离第i个数最近的满足子序列的数,也就是依次将前i-1个数与第i个数进行比较,如果小于第i个数,那么这个就是以第i个元素结尾的一个子序列(只有遍历所有的前i-1个数才知道离它最近的是哪一个),但是需要注意的是存在一个边界问题,就是f[i]至少等于1,所以每次在遍历的时候都需要初始化f[i] = 1
C++ 代码
#include<iostream>
using namespace std;
const int N = 1010;
int n;
int a[N], f[N];
int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; i++)
scanf("%d", &a[i]);
for(int i = 1; i <= n; i++)
{
f[i] = 1; // f[i]至少等于1,当只有a[i]的时候,所以初始化a[i] = 1
for(int j = 1; j < i; j++)
if(a[j] < a[i]) f[i] = max(f[i], f[j] + 1);
}
int res = 0;
for(int i = 1; i <= n; i++) res = max(res, f[i]);
cout << res << endl;
return 0;
}