AcWing 895. 最长上升子序列
原题链接
简单
作者:
jasonlin
,
2020-03-25 23:06:18
,
所有人可见
,
阅读 2558
题目描述
给定一个长度为N的数列,求数值严格单调递增的子序列的长度最长是多少。
输入格式
第一行包含整数N。
第二行包含N个整数,表示完整序列。
输出格式
输出一个整数,表示最大长度。
数据范围
1≤N≤1000,
−109≤数列中的数≤109
样例
输入样例:
7
3 1 2 1 8 5 6
输出样例:
4
算法1
(暴力枚举) $O(n^2)$
- 状态表示
dp[i]
- 集合: 所有
以第i个数字结尾
的上升子序列的集合
- 属性: 集合中的子序列长度的
最大值
- 状态计算
- 枚举上升子序列的
倒数第二数
,不妨以坐标j
表示,若 a[j] < a[i]
则 dp[i] =max(dp[i], dp[j] + 1)
- 备注
- 需要注意的是dp的长度取法不同, 对应的
a[j] a[i]
的坐标细节不同
C++ 代码
#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
int N;
cin >> N;
int a[N];
for(int i = 0; i < N; i++)scanf("%d ", &a[i]);
int dp[N + 1] ; // 因为用的值 之前会计算出来,所以可以不用 `int dp[N+1] = {0};
int res = 0;
for(int i = 1; i <= N; i++) // i从1 开始 所以 <= N
{
dp[i] = 1;
for(int j = 1; j < i; j++)
{
if(a[j - 1] < a[i - 1])
dp[i] = max(dp[i], dp[j] + 1);
}
res = max(res ,dp[i]);
}
cout << res << endl;
return 0;
}
为什么不能直接初始化dp数组全为1
可以啊 ,
为什么j需要小于i?
f(i)表示的是以i结尾的子序列, 所以前遍历到i,所以
1<= j < i
N是变量,不会报错吗?
我也纳闷这个问题,按理说不能用变量初始化数组的大小;有时候这么写能过,有时候不能过,查了下好像是看c++ 的标准 或者编译器的版本; 我这么写是有点风险的;
C++ 新标准,这样写不会报错,但是如果N过大,主函数内数组申请不了那么大的内存会导致爆栈。
谢谢解答