题目:POJ 2533 Longest Ordered Subsequence
Description
A numeric sequence of ai is ordered if a1 < a2 < ... < aN. Let the subsequence of the given numeric sequence (a1, a2, ..., aN)
be any sequence (ai1, ai2, ..., aiK), where 1 <= i1 < i2 < ... <iK <= N. For example, sequence
(1, 7, 3, 5, 9, 4, 8) has ordered subsequences, e. g., (1, 7), (3, 4, 8) and many others. All longest ordered subsequences are of length 4, e. g., (1, 3, 5, 8).
Your program, when given the numeric sequence, must find the length of its longest ordered subsequence.
思路1:最常用的方法是二维的动态规划,dp[i]表示0~i以data[i]结尾的最长递增子序列,则dp[i]等于所有data[i]前面的且比data[i]小的数的最长递增子序列的最大值加1,即dp[i] = max(dp[j]+1,1),其中{j < i && data[j] < data[i]},具体代码如下:
#include<iostream> #include<vector> using namespace std; int LIS(vector<int> data) { int length = data.size(),i,j,res = 1; if(length == 0)return 0; vector<int> dp(length,1); for(i = 1; i < length;++i) { for(j = 0;j < i;++j) { if(data[j] < data[i] && dp[j] + 1 > dp[i])dp[i] = dp[j] + 1;//状态转移方程 } if(dp[i] > res)res = dp[i]; } return res; } int main() { int n,i; while(cin >> n) { vector<int> data(n); for(i = 0; i < n;++i)cin >> data[i]; cout << LIS(data) << endl; } return 0; }
思路2:dp[i]表示长度为i的递增子序列的最大值最小的元素,例如(1,7,3,5,9,4,8),则长度为4的子序列有(1,3,5,9)和(1,3,5,8),则dp[4]为8。这样,我们遍历数组data,利用二分查找把data[i]插入到dp的相应位置上,最后dp的长度即为最大长度,具体如下:
#include<iostream> #include<vector> using namespace std; int LIS(vector<int> data) { int length = data.size(),i,j,res = 1; if(length == 0)return 0; vector<int> dp(length,0); dp[0] = data[0]; for(i = 1; i < length;++i) { int left = 0,right = res-1; while(left <= right)//寻找以data[i]结尾的最长递增子序列 { int mid = left + ((right - left) >> 1); if(dp[mid] < data[i])left = mid + 1; else right = mid - 1; } dp[left] = data[i]; //表示data[i]应该放在长度为left+1的子序列的最后一个元素上 if(left >= res)res = left+1;//更新最大长度 } return res; } int main() { int n,i; while(cin >> n) { vector<int> data(n); for(i = 0; i < n;++i)cin >> data[i]; cout << LIS(data) << endl; } return 0; }
poj之最长递增子序列