动态规划之最长上升子序列(未完待续)
2018-03-29 16:42
309 查看
动态规划之最长上升子序列(未完待续)
问题描述
输入数据输入的第一行是序列的长度N (1 <= N <= 1000)。第二行给出
序列中的N个整数,这些整数的取值范围都在0到10000。
输出要求
最长上升子序列的长度。
输入样例
7
1 7 3 5 9 4 8
输出样例
4
输入样例
9
2 7 1 5 6 4 3 8 9
输出样例
5
解法一:递归式
在这里遇到了障碍#include<iostream> #define MAX 1000 using namespace std; int a[MAX]; int has_smaller(int n) { int i = 0; for(i = n-1; i>=0; i--) { if(a[i] <= a ) return i; } return -1; } /* Longest increasing subsequence ******************************* not finished yet! ******************************* */ int LIS(int n) { int i = has_smaller(n); int j = 0; if(i == -1) return 1; return LIS(i) + 1; } int main() { int n = 0; int i = 0; cin >> n; for(i = 0; i<n; i++) { cin >> a[i]; } cout << LIS(n-1)<<endl; return 0; }
解法二:递推式
对于每一个元素a[i]而言,len[i] = len(z) + 1 , j<=i且a[j] <=a[i],而z是所有满足条件的j中len(j)最大的那一个。若不存在满足上述条件的j,则len(i) = 1。#include<iostream> #define MAX 10005 using namespace std; int a[MAX]; int b[MAX]; // longest increasing subsequence void LIS(int n) { int i= 0; int j = 0; int sign = 0; for(i = 0; i<n; i++) { sign = 0; for(j = i-1; j>=0; j--) { if(a[j]<a[i] && b[j]>=b[i]) { b[i] = b[j]; sign = 1; } } if(sign == 1) b[i]++; } } int main() { int n = 0; int result = 0; cin >> n; for(int i = 0; i<n; i++) { cin >> a[i]; b[i] = 1; } LIS(n); for(int i = 0; i<n; i++) { if(result<b[i]) result = b[i]; } cout << result <<endl; return 0; }
解法三:贪心加二分
此解法的思想是用一个一维数组来存储寻找子序列过程中值的变化情况:a中的当前的元素若大于或等于一维数组的最后一个有效元素,那么就把它加入到一维数组中作为数组的最后一个元素。如果小于,那么就在一维数组中找到第一个比它大的元素并替换掉。这样最后一维数组中的所有有效元素就构成了一个最长上升子序列。另外,在找一维数组中第一个比a中当前元素大的元素时,可以采用二分查找的形式。要注意这里的二分查找不是普通的二分查找,而是要找上确界。
综合考虑,此解法的时间复杂度为O(n*log n)。
#include<iostream> #define MAX 10000 using namespace std; int a[MAX]; int b[MAX]; int binary_search(int n,int a) { int head = 1; int tail = n; int middle = 0; while(head < tail) { middle = tail - (tail - head)/2; if(b[middle-1] <= a && b[middle] >=a) return middle; if(b[middle] < a) { head = middle; } else if(b[middle-1] > a ) { tail = middle - 1; } } return 1; } int LIS(int n) { int i = 0; int max_len = 0; int search_result = 0; for(i = 0; i<n; i++) { if(b[max_len] <= a[i]) { b[++max_len] = a[i]; } else { b[binary_search(max_len, a[i])] = a[i]; abb6 } } return max_len; } int main() { int n = 0; int i = 0; cin >> n; for(i = 0; i<n; i++) { cin >> a[i]; } cout << "The longest increasing subsequence\'s length is: "; cout <<LIS(n)<<endl; return 0; }
相关文章推荐
- 动态规划----求最长上升子序列
- 初识动态规划-最长不上升子序列
- 动态规划-最长上升子序列(LIS)
- 动态规划―最长上升子序列
- 动态规划之编号动态规划:hdu 1025(dp+二分 求最长上升子序列)
- c++动态规划基础——最长上升子序列
- 动态规划7:最长上升子序列LIS
- 动态规划-最长上升子序列(LIS)
- 动态规划入门 COGS1398 最长上升子序列
- 算法基础之python实现动态规划中数字三角形和最长上升子序列问题
- 动态规划——最长上升子序列
- 动态规划:最长上升子序列
- 动态规划_最长上升子序列LIS
- 动态规划6-最长上升子序列
- nlog(n)解动态规划--最长上升子序列(Longest increasing subsequence)
- 动态规划:最长上升子序列
- 动态规划:最长上升子序列
- 算法学习之动态规划--最长上升子序列
- POJ1631——Bridging signals(动态规划,最长上升子序列应用)
- HDU 1160(动态规划-最长上升子序列)