最长递增子序列
2017-06-16 09:39
197 查看
//方法一:直接动态规划 #include<bits/stdc++.h> using namespace std; int main() { int n,dp[1000]; while(cin>>n) { vector<int> v(n); memset(dp,0,sizeof(dp)); for(int i=0; i<n; i++) cin>>v[i]; for(int i=0; i<n; i++) for(int j=0; j<i; j++) if(v[i]>v[j]) dp[i]=max(dp[i],dp[j]+1); int Max=0; for(int i=0; i<n; i++) if(Max<dp[i])Max=dp[i]; cout<<Max+1<<endl; } return 0; } /*注意!!!方法二测试只通过90%,原因是所求递增序列中可能存在相等的数,而题目中要求不能相同 这个跟最长回文子序列有点像: (1)最长回文子序列:求原序列与逆序列最长公共子序列 (2)最长递增子序列(含相同元素):求原序列与排序序列最长公共子序列 */ //方法二:转化为最长公共子序列问题, #include<bits/stdc++.h> using namespace std; int main() { int n,dp[1000][1000]; while(cin>>n) { vector<int> v(n); memset(dp,0,sizeof(dp)); for(int i=0; i<n; i++) cin>>v[i]; vector<int> v1(v); sort(v1.begin(),v1.end()); for(int i=0; i<n; i++) for(int j=0; j<n; j++) if(v[i]==v1[j]) dp[i+1][j+1]=dp[i][j]+1; else dp[i+1][j+1]=max(dp[i][j+1],dp[i+1][j]); cout<<dp <<endl; } return 0; } /* unsigned int LISS(const int array[], size_t length, int result[]) { unsigned int i, j, k, max; //变长数组参数,C99新特性,用于记录当前各元素作为最大元素的最长递增序列长度 unsigned int liss[length]; //前驱元素数组,记录当前以该元素作为最大元素的递增序列中该元素的前驱节点,用于打印序列用 unsigned int pre[length]; for(i = 0; i < length; ++i) { liss[i] = 1; pre[i] = i; } for(i = 1, max = 1, k = 0; i < length; ++i) { //找到以array[i]为最末元素的最长递增子序列 for(j = 0; j < i; ++j) { //如果要求非递减子序列只需将array[j] < array[i]改成<=, //如果要求递减子序列只需改为> if(array[j] < array[i] && liss[j] + 1> liss[i]) { liss[i] = liss[j] + 1; pre[i] = j; //得到当前最长递增子序列的长度,以及该子序列的最末元素的位置 if(max < liss[i]) { max = liss[i]; k = i; } } } } //输出序列 i = max - 1; while(pre[k] != k) { result[i--] = array[k]; k = pre[k]; } result[i] = array[k]; return max; } unsigned int LISSEx(const int array[], size_t length, int result[]) { unsigned int i, j, k, l, max; //栈数组参数,C99新特性,这里的liss数组与上一个函数意义不同,liss[i]记录长度为i + 1 //递增子序列中最大值最小的子序列的最后一个元素(最大元素)在array中的位置 unsigned int liss[length]; //前驱元素数组,用于打印序列 unsigned int pre[length]; liss[0] = 0; for(i = 0; i < length; ++i) { pre[i] = i; } for(i = 1, max = 1; i < length; ++i) { //找到这样的j使得在满足array[liss[j]] > array[i]条件的所有j中,j最小 j = 0, k = max - 1; while(k - j > 1) { l = (j + k) / 2; if(array[liss[l]] < array[i]) { j = l; } else { k = l; } } if(array[liss[j]] < array[i]) { j = k; } //array[liss[0]]的值也比array[i]大的情况 if(j == 0) { //此处必须加等号,防止array中存在多个相等的最小值时,将最小值填充到liss[1]位置 if(array[liss[0]] >= array[i]) { liss[0] = i; continue; } } //array[liss[max -1]]的值比array[i]小的情况 if(j == max - 1) { if(array[liss[j]] < array[i]) { pre[i] = liss[j]; liss[max++] = i; continue; } } pre[i] = liss[j - 1]; liss[j] = i; } //输出递增子序列 i = max - 1; k = liss[max - 1]; while(pre[k] != k) { result[i--] = array[k]; k = pre[k]; } result[i] = array[k]; return max; } 一 问题描述 设序列L = <a1, a2, a3, ..., an>是长度为n的序列,L的一个递增序列描述为:<ai1, ai2,..., aik>, 其中下标序列 <i1, i2, ..., ik>是 递增的, 子序列<ai1, ai2, ...., aik> 也是递增的。此递增序列的长度为 k 二 解法1, 转化为LCS问题 先把序列 L 按照从小到大的顺序排列, 得到另一个序列S,再求L和S的最长公共子序列 三 解法2,动态规划 另 len[i] 表示以第 i 个元素结尾的最长递增子序列的长度,最后求出 max { len[i] } 即可 实例 <1, 3, 4, 2, 7> len[1] = 1, 以1结尾的最长递增子序列是<1>, 长度为1 len[2] = 2, 以3结尾的最长递增子序列是<1,3>, 长度为2 len[3] = 3, 以4结尾的最长递增子序列是<1, 3, 4>, 长度为3 len[4] = 2, 以2结尾的最长递增子序列是<1, 2>,长度为2 那么,如何求len[5]呢?转化为下面的子问题: 第5个元素等于7,找到一个序号在a[5]前面且小于a[5]的元素a[i], 以a[i]结尾的最长递增子序列加上a[5], 组成一个新的最长递增子序列,其 长度比原来的多1。比a[5]小的元素有多个(最多4个),那么得到的递增子序列也有多个,其中最长的那个就等于以a[5]结尾的最长递增子序列。 例中,a[3 ]比a[5]小,而且以a[3]结尾的最长递增子序列是最长的, 故以a[5]结尾的递增子序列长度在其基础上加1,等于4 len[5] = 4, 以5结尾的最长递增子序列是<1,3,4,5>,长度为4 四 解法3,对解法2的改进 解法2中,求len[i]的时候, 要从a[1], ... a[i-1]中找出所有比 a[i] 小的元素,而a[1], ... a[i-1]是无序的。查找速度比较慢。 引出数组 f[k] 表示长度等于k的递增子序列中最末尾的元素, 长度越长的序列,其末尾元素也越大,所以f[k]是递增的。 实例 <1, 3, 4, 2, 7> len[1] = 1, f[1] = a[1] = 1 len[2] = 2, f[2] = a[2] = 3 len[3] = 3, f[3] = a[3] = 4 len[4] = 2, f[2] = a[4] = 2 ( 更新了f[2] ) 那么,如何求len[5] 呢? f[1] = 1, f[2] = 2, f[3] = 4, a[5] = 7, 找出末尾元素比a[5]小,而且长度最长的递增子序列,此例中, f[3] = 4 表示长度等于3的子序列,其末尾元素为4,这个子序列的长度最长。 a[5]加上此序列形成的新序列长度为4, 然后更新f[4] = a[5] = 7,表示长度 等于4的子序列,其末尾元素等于7 在上面的步骤中,找出末尾元素比a[i]小,而且长度最长的子序列,其实就是 对于f[1], ...f[k], 从后往前找,第一个比a[i]小的元素就是长度最长的子序列。查找的时候 可以用二分查找方法。故比解法1更快。 */
相关文章推荐
- 最长递增子序列问题
- 最长递增子序列(LCS)
- 动态规划___记录路径的最长递增子序列
- 最长递增子序列的O(NlogN)算法
- 最长递增子序列(原创)
- 动态规划求最长递增子序列
- 求解最长递增子序列的长度
- 最长递增子序列 O(NlogN)算法
- 最长递增子序列 O(NlogN)算法
- 最长递增子序列O(NlogN)算法
- 最长递增子序列问题 nyoj 17单调递增最长子序列 nyoj 79拦截导弹
- 最长递增子序列
- 最长递增子序列
- 最长递增子序列
- HDU - 1087 Super Jumping! Jumping! Jumping!(最长递增子序列)
- 最长递增子序列O(NlogN)算法(leetcode 300. Longest Increasing Subsequence )
- (java)求最长递增子序列(可以不连续的情况)
- 求解最长递增子序列长度|动态规划+二分查找:C\C++实现
- 最长递增子序列
- 编程之美 求数组中的最长递增子序列