最长上升子序列
最长上升子序列
给定一个长度为 NN 的数列,求数值严格单调递增的子序列的长度最长是多少。
输入格式
第一行包含整数 NN。
第二行包含 NN 个整数,表示完整序列。
输出格式
输出一个整数,表示最大长度。
数据范围
1≤N≤10001≤N≤1000,
−109≤数列中的数≤109−109≤数列中的数≤109
输入样例:
7
3 1 2 1 8 5 6
输出样例:
4
关于动态规划,我们应该想一个问题,就是如何去规划步骤,我们思考,到如何走到这一步,和这一步的情况是什么样,这样说或许有些抽象。
我们看以下这个例子
例如:
3 1 2 1 8 5 6
按照题意,假设我们走到8
可能有以下几种情况。
{1,2,8}
{1,8}
{2,8}
那我们只需要最优子结构就好,也就是1,2,8这个情况。
那么我们是不是可以遍历 用dp[i]存储我们最优情况,那么我们要思考,没个最优子结构应该如何推导?
考虑dp[i]可以由哪些状态得到
//如果vec[i] < vec[j]
可以由前面的最大max(dp[j]+1,dp[i])得来。
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (vec[i] < vec[j]) {
vecdp[j] = max(vecdp[j], vecdp[i] + 1);
}
}
}
每次在满足vec[i] < vec[j]的情况下,做出两种转移,dp[前面]+1是最优解和此时已得到的是最优解推导而来。
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int N = 1e5;
vector<int> vec(N);
vector<int> vecdp(N);
int main() {
int n;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> vec[i];
}
vecdp.resize(n + 5);
fill(vecdp.begin(), vecdp.end(), 1);
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (vec[i] < vec[j]) {
vecdp[j] = max(vecdp[j], vecdp[i] + 1);
}
}
}
int ans = *max_element(vecdp.begin(), vecdp.begin() + n);
cout << ans;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现