首页 > 其他分享 >【动态规划】最长上升子序列(Longest Increasing Subsequence)问题以及输出具体方案

【动态规划】最长上升子序列(Longest Increasing Subsequence)问题以及输出具体方案

时间:2025-01-20 10:43:14浏览次数:1  
标签:begin end 迭代 int 元素 maxLen Subsequence Longest Increasing

最长上升子序列

两道模板题(一样的)
洛谷 B3637 最长上升子序列
AcWing 895. 最长上升子序列

题目描述

这是一个简单的动规板子题。

给出一个由 \(n(n\le 5000)\) 个不超过 \(10^6\) 的正整数组成的序列。请输出这个序列的最长上升子序列的长度。

最长上升子序列是指,从原序列中按顺序取出一些数字排在一起,这些数字是逐渐增大的。

输入格式

第一行,一个整数 \(n\),表示序列长度。

第二行有 \(n\) 个整数,表示这个序列。

输出格式

一个整数表示答案。

样例 #1

样例输入 #1

6
1 2 4 1 3 4

样例输出 #1

4

提示

分别取出 \(1\)、\(2\)、\(3\)、\(4\) 即可。


标准模版代码

#include <iostream>

using namespace std;

const int N = 5010;//洛谷板子题是5000所以开大点

int n;
int f[N], a[N];

int main()
{
    scanf("%d", &n);
    for (int i = 0; i < n; i++) 
    {
        scanf("%d", &a[i]);
        f[i] = 1;//初始子序列只有一个字母时长度为1
    }

    for (int i = 0; i < n; i++)
        for (int j = 0; j < i; j++)
        {
            if (a[j] < a[i]) //上升
                f[i] = max(f[i], f[j] + 1);//最长
        }

    int res = 0;
    for (int i = 0; i < n; i++) res = max(res, f[i]);
    printf("%d", res);
    return 0;
}

输出具体方案

代码解释1int maxLen = *max_element(f.begin(), f.end());

// 代码整体功能:
// 这段代码的目的是在一个整数容器 f 中找到最大的元素,并将其存储在 maxLen 变量中。

// 代码解释:
// 首先,我们使用了标准库中的 max_element 函数。
// max_element 函数接受两个迭代器作为参数,这里是 f.begin()f.end()
// f.begin() 表示容器 f 的起始迭代器,f.end() 表示容器 f 的结束迭代器。
// 这个函数会遍历 f 容器中的元素,从 f.begin() 开始,直到 f.end() 之前的元素。
// 然后,它会找出这些元素中的最大值。

// 接着,max_element 函数返回一个迭代器,该迭代器指向容器中最大元素的位置。
// 由于 max_element 函数返回的是一个迭代器,而我们想要的是元素的值,
// 所以在函数调用前使用 * 运算符进行解引用操作。
// 这将迭代器指向的元素的值提取出来,并存储在 maxLen 变量中。

代码解释2int k = find(f.begin(), f.end(), maxLen) - f.begin();

// 代码整体功能:
// 这段代码的目的是在容器 f 中查找元素 maxLen 的位置,并将该位置存储在变量 k 中。

// 代码解释:
// 首先,使用 find 函数来查找元素。find 函数接受三个参数:
// 1. 起始迭代器 f.begin(),表示从容器 f 的开始位置开始查找。
// 2. 结束迭代器 f.end(),表示查找范围截止到容器 f 的末尾位置(不包括 f.end() 所指向的元素)。
// 3. 要查找的元素 maxLen,它是之前代码中找出的容器 f 中的最大元素。

// find 函数会在 f.begin()f.end() 的范围内查找第一个等于 maxLen 的元素。
// 如果找到了,find 函数会返回一个迭代器,该迭代器指向找到的元素。
// 如果没找到,find 函数会返回 f.end()

// 然后,通过 find(f.begin(), f.end(), maxLen) - f.begin() 计算元素 maxLen 在容器中的位置:
// 用 find 函数返回的迭代器减去 f.begin() 迭代器,得到的结果是一个整数,表示元素 maxLen
相对于容器 f 起始位置的偏移量。
// 这个偏移量存储在变量 k 中。

代码解释3cout << path[i] << " \n"[i == path.size() - 1];

" \n"[i == path.size() - 1];:这是一个比较巧妙的写法。" \n"是一个字符串常量,它包含一个空格和一个换行符。
[i == path.size() - 1]是一个条件表达式,当i等于path.size() - 1(即遍历到最后一个元素)时,表达式的值为 1,此时取字符串" \n"中的第二个字符(即换行符\n);否则表达式的值为 0,取字符串" \n"中的第一个字符(即空格)。这样做的效果是,除了最后一个元素输出后换行,其他元素输出后都跟一个空格。

输出具体方案代码

#include <algorithm>
#include <iostream>
#include <vector>

using namespace std;

int main()
{
    int n = 0;
    cin >> n;

    vector<int> a(n, 0); // 原数组
    vector<int> f(n, 1); // 状态
    vector<int> g(n, 0); // 具体方案

    for (int i = 0; i < n; i++) cin >> a[i];

    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < i; j++)
        {
            if (a[j] < a[i])
            {
                if (f[i] < f[j] + 1)
                {
                    f[i] = f[j] + 1;
                    g[i] = j; // 记录i是由j更新的
                }
            }
        }
    }

    int maxLen = *max_element(f.begin(), f.end());
    int k = find(f.begin(), f.end(), maxLen) - f.begin();

    vector<int> path;
    for (int i = 0; i < maxLen; i++)
    {
        path.push_back(a[k]);
        k = g[k];
    }

    reverse(path.begin(), path.end());
    for (int i = 0; i < path.size(); i++)
    {
        cout << path[i] << " \n"[i == path.size() - 1];
    }
    return 0;
}

标签:begin,end,迭代,int,元素,maxLen,Subsequence,Longest,Increasing
From: https://www.cnblogs.com/Tshaxz/p/18680885

相关文章

  • [LeetCode] 1370. Increasing Decreasing String 上升下降字符串
    Youaregivenastring s.Reorderthestringusingthefollowingalgorithm:Removethe smallest characterfrom s and append ittotheresult.Removethe smallest characterfrom s thatisgreaterthanthelastappendedcharacter,and append itt......
  • AT_abc248_h [ABC248Ex] Beautiful Subsequences 题解
    题目传送门前置知识树状数组|序列分治解法考虑序列分治,设因\(\max\)和\(\min\)形成的分节点先后为\(k_{1},k_{2}\)。对于\(j\in(mid,k_{1}]\),等价于统计满足\(\max\limits_{h=i}^{mid}\{a_{h}\}-\min\limits_{h=i}^{mid}\{a_{h}\}\lej-i+k\)的\(j\)的......
  • [ARC138E] Decreasing Subsequence
    [ARC138E]DecreasingSubsequence题意给出\(3\leqn\leq5000,2\leqk\leq(n+1)/2\),对所有长度为\(n\)的满足\(0\leqa_i\leqi\)且正数项两两不同的序列\(a\),求长度为\(k\)的元素非\(0\)的下降子序列个数之和。思路先刻画序列。对所有\(a_i\)减去\(1\),新......
  • [LeetCode] 2730. Find the Longest Semi-Repetitive Substring
    Youaregivenadigitstringsthatconsistsofdigitsfrom0to9.Astringiscalledsemi-repetitiveifthereisatmostoneadjacentpairofthesamedigit.Forexample,"0010","002020","0123","2002",and&quo......
  • CF1988C. Increasing Sequence with Fixed OR
    链接:    https://codeforces.com/problemset/problem/1988/Chttps://codeforces.com/problemset/problem/1988/C大意:    给定一个n,找一个最长的正整数递增序列,并满足相邻或等于n思路:    1、显然是要分析二进制方面的规律        2、首先......
  • LeetCode 1371. Find the Longest Substring Containing Vowels in Even Counts
    原题链接在这里:https://leetcode.com/problems/find-the-longest-substring-containing-vowels-in-even-counts/description/题目:Giventhestring s,returnthesizeofthelongestsubstringcontainingeachvowelanevennumberoftimes.Thatis,'a','e&......
  • CF1621G Weighted Increasing Subsequences 题解
    题目链接点击打开链接题目解法这种题就感觉每一步都不难想,但串在一起就不会显然考虑位置\(x\)作为\(lis\)的一部分,合法的\(lis\)的个数合法的约束是:令\(lis\)的最后一个位置为\(last\),满足\(\max\{a_{last+1},...,a_n\}>a_x\)不难发现,合法的\(last\)是一段区间......
  • 浙大数据结构:01-复杂度2 Maximum Subsequence Sum
    数据结构MOOCPTA习题01-复杂度2MaximumSubsequenceSum#include<iostream>usingnamespacestd;constintM=100005;inta[M];intmain(){ intk; cin>>k; intf=1; for(inti=0;i<k;i++) { cin>>a[i]; if(a[i]>=0)//如......
  • CF 2001 D. Longest Max Min Subsequence(*1900) 思维
    CF2001D.LongestMaxMinSubsequence(*1900)思维题目链接题意:给你一个长度为\(n\)的序列\(a\),设\(S\)是\(a\)的所有可能的非空子序列的集合,且没有重复的元素。你的目标是找出\(S\)中最长的序列。如果有多个序列,请找出将奇数位置上的项乘以\(−1\)后,使词序最小......
  • 题解:SP3109 STRLCP - Longest Common Prefix
    三倍经验:UVA11996JewelMagicP4036[JSOI2008]火星人题意维护一个字符串\(S\),支持以下操作:\(Q\i\j\):输出\(\operatorname{LCP}(S[i\dotsl],S[j\dotsl])\)\(R\i\char\):用\(char\)替换\(S\)的第\(i\)个字符\(I\i\char\):在\(S\)的第\(i\)......