最长上升子序列

最长上升子序列

给定一个长度为 NN 的数列,求数值严格单调递增的子序列的长度最长是多少。

输入格式

第一行包含整数 NN

第二行包含 NN 个整数,表示完整序列。

输出格式

输出一个整数,表示最大长度。

数据范围

1N10001≤N≤1000
109109−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;
}

 

posted @   安娜アンナ  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示