计蒜客-程序设计竞赛入门
2016-07-18 15:19
246 查看
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 个整数,表示序列中的每个元素。
输出格式:
输出只有一行,为最长上升子序列的长度。样例输入:
51 5 2 3 4
样例输出:
4我们首先要把问题拆分成很多子问题。对于这道题来说,我们分解为这样的N个子问题:求解最后一个元素为原数组中第 i (1 ≤ i ≤ n)个元素的最长上升子序列的长度。 如果我们把N个问题都计算出来了,那么最终结果就从所有子问题中选出一个最大值是不是就可以啦?
#include <iostream> #include <cstdio> using namespace std; int n, dp[101], num[101], result = 0; int main() { scanf("%d", &n); for (int i = 1; i <= n; ++i) { scanf("%d", &num[i]); } // begin: 在下面实现动态规划的核心代码 for(int i=1;i<=n;++i){ dp[i]=1; //最小升序列长度自然是1 for (int j=1;j<i;++j){ if(num[j]<num[i]){ dp[i]=max(dp[j]+1,dp[i]); //printf ("%d %d#1\n",dp[i],i); } } result=max(result,dp[i]); // printf ("%d#2\n",result); } // end. printf("%d\n", result); return 0; }
总结:
当我们求解以第三个元素为结尾的最长上升子序列长度 len[3] 时,已经求得之前所有的解(len[1], len[2]),而第三个元素 2 要比第一个元素 1 大,却比第二个元素 5 小。所以第三个元素的解可以通过第一个元素的解+1 更新得到。所以我们在求 dp[i] 的时候,只要把前面比第i个元素小的位置对应的 dp 值+1 再计算出最大值即可。相关文章推荐
- C++动态规划之最长公子序列实例
- C++动态规划之背包问题解决方法
- C#使用动态规划解决0-1背包问题实例分析
- 动态规划
- C++ 动态规划
- 动态规划解决背包问题的核心思路
- DP(动态规划) 解游轮费用问题
- 动态规划的用法——01背包问题
- 动态规划的用法——01背包问题
- 《收集苹果》 动态规划入门
- 《DNA比对》蓝桥杯复赛试题
- 《背包问题》 动态规划
- 自顶向下动态规划解决最长公共子序列(LCS)问题
- 01背包问题
- 初学ACM - 半数集(Half Set)问题 NOJ 1010 / FOJ 1207
- 关于爬楼梯的动态规划算法
- 动态规划 --- hdu 1003 **
- DP问题各种模型的状态转移方程
- 0-1背包解题过程
- 背包问题