最长递增子序列的个数(200分 / 动态规划)

题目描述 :给定一个整数数组 nums(长度 n ≤ 2000,元素范围 -10^6 ~ 10^6),求最长严格递增子序列 的个数。若最长递增子序列长度为 L,输出长度为 L 的不同子序列个数(下标不同即视为不同)。

输入:

  • 第一行:n

  • 第二行:n 个整数

输出:最长递增子序列的个数。

示例:

text

复制代码
输入:
5
1 3 5 4 7

输出:
2

解释:最长递增子序列长度为 4,有两个:1 3 5 7 和 1 3 4 7。

解题思路

维护两个数组:

  • dp[i]:以 nums[i] 结尾的最长递增子序列长度。

  • cnt[i]:以 nums[i] 结尾的最长递增子序列个数。

转移:

  • 若 nums[j] < nums[i]:

    • 若 dp[j] + 1 > dp[i]:dp[i] = dp[j] + 1,cnt[i] = cnt[j]

    • 若 dp[j] + 1 == dp[i]:cnt[i] += cnt[j]

最后统计所有 dp[i] == L 的 cnt[i] 之和。

参考代码

c

复制代码
#include <stdio.h>

int main(void) {
    int n;
    scanf("%d", &n);

    int nums[2005];
    for (int i = 0; i < n; i++) scanf("%d", &nums[i]);

    int dp[2005];
    long long cnt[2005]; // 个数可能较大,用 long long

    for (int i = 0; i < n; i++) {
        dp[i] = 1;
        cnt[i] = 1;
    }

    int maxLen = 1;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < i; j++) {
            if (nums[j] < nums[i]) {
                if (dp[j] + 1 > dp[i]) {
                    dp[i] = dp[j] + 1;
                    cnt[i] = cnt[j];
                } else if (dp[j] + 1 == dp[i]) {
                    cnt[i] += cnt[j];
                }
            }
        }
        if (dp[i] > maxLen) maxLen = dp[i];
    }

    long long ans = 0;
    for (int i = 0; i < n; i++) {
        if (dp[i] == maxLen) ans += cnt[i];
    }

    printf("%lld\n", ans);
    return 0;
}
相关推荐
镜子AI1 小时前
教培机构多模态内容跨模态检索系统:基于CLIP的统一表征与图文混合召回算法
人工智能·python·算法·机器学习
小宋10211 小时前
合成评测集怎么造才不“自嗨”:自动出题、去重、泄漏检测与人工抽检
人工智能·算法·机器学习
蒸蒸yyyyzwd1 小时前
秋招笔记day58
算法·哈希算法
Jasmine_llq1 小时前
《P5663 [CSP-J 2019] 加工零件》
数据结构·算法·bfs·广度优先搜索·分层 bfs /·奇偶分层最短路·奇数最短步数
在所不辞兄2 小时前
分层PINN提升多物理场一致性
人工智能·神经网络·算法·机器学习·工程仿真
wanderist.2 小时前
CSP 第43次认证 T4:集合划分 —— 图染色与二分图判定
算法·图论
不做无法实现的梦~2 小时前
基于 PX4 的全仓库架构、无人机算法解析与开发学习规划
算法·架构·无人机
做cv的小昊2 小时前
【大模型算法自学笔记01】NLP基础知识(1.1 自注意力)
人工智能·笔记·算法·自然语言处理·大模型·llm
stolentime2 小时前
AT_arc182_a [ARC182A] Chmax Rush!题解
数据结构·c++·算法·动态规划