计蒜客课程竞赛入门--最长上升子序列(LIS) 流程记

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了计蒜客课程竞赛入门--最长上升子序列(LIS) 流程记相关的知识,希望对你有一定的参考价值。

最长上升子序列 (Longest Increasing Subsequence, 常简称为 LIS) 是动态规划解决的一个经典问题。

我们先讲一下子序列是什么。一个数组的子序列就是从里面选出一些元素,并将他们保持原有的先后顺序排列。比如[1, 2, 3, 4, 5]的子序列有[1, 3, 5]、[3, 4],而[1, 5, 3]则不是这个数组的子序列。

这里多介绍一下,还有一个容易与子序列混淆的概念:子串。子串是指从一个数组中选出连续的一个或多个元素,并且保持他们原有的顺序。子串一定是子序列,比如前面的子序列[3, 4]就是子串,但[1, 3, 5]不是子串,因为这三个元素在原数组中并不是连续的。

一句话总结他们的区别,就是子序列可以不连续,而子串必须连续。

上升子序列是指子序列Ai中满足 A1 < A2 < ... < An,也就是后面的元素一定比前面的元素大,比如(1, 3, 5)是上升子序列,(1, 3, 3)和(1, 4, 3)都不是。现在来跟我一起解决最长上升子序列的问题吧!(o??o)/

输入格式:

第一行一个整数n(1 ≤ n ≤ 100),表示序列的长度。

第二行 n 个整数,表示序列中的每个元素。

输出格式:

输出只有一行,为最长上升子序列的长度。

样例输入:

5

1 5 2 3 4

样例输出:

4

还记得上一道数塔问题我们怎么解决的么?我们首先要把问题拆分成很多子问题。对于这道题来说,我们分解为这样的N个子问题:求解最后一个元素为原数组中第 i (1 ≤ i ≤ n)个元素的最长上升子序列的长度。

如果我们把N个问题都计算出来了,那么最终结果就从所有子问题中选出一个最大值是不是就可以啦?好了,我们开始写代码吧。

 

//注释:子序列并非一定连续,这里的dp仅提供长度.

 

 

 1 #include <iostream>
 2 #include <cstdio>
 3 using namespace std;
 4 int n, dp[101], num[101], result = 0;
 5 int main() {
 6     scanf("%d", &n);
 7     for (int i = 1; i <= n; ++i) {
 8         scanf("%d", &num[i]);
 9     }
10     // begin: 在下面实现动态规划的核心代码
11     for(int i=1;i<=n;i++)
12     {
13         dp[i]=1;
14         for(int j=1;j<i;j++)
15         {
16             if(num[j]<num[i]){
17                 dp[i]=max(dp[j]+1,dp[i]);
18             }
19         }
20        result=max(result,dp[i]);
21     }
22     // end.
23     printf("%d\n", result);
24     return 0;
25 }

 

以上是关于计蒜客课程竞赛入门--最长上升子序列(LIS) 流程记的主要内容,如果未能解决你的问题,请参考以下文章

计蒜客课程竞赛入门--堆排序 流程记

计蒜客课程竞赛入门--数塔问题(DP) 流程记

计蒜客课程竞赛入门--统计三角形 代码流程摘记

计蒜客课程竞赛入门--冗余关系(并查集) 流程记

计蒜客课程竞赛入门--二叉搜索树 流程记

计蒜客课程竞赛入门--最近通话记录(STL队列) 流程记