【DP|LIS】POJ-2533 Longest Ordered Subsequence(O(n^2)、O(nlogn))
来源:互联网 发布:黑马软件科技有限公司 编辑:程序博客网 时间:2024/05/16 05:34
Description
Your program, when given the numeric sequence, must find the length of its longest ordered subsequence.
Input
Output
Sample Input
71 7 3 5 9 4 8
Sample Output
4
Source
————————————————————无力的分割线————————————————————
O(n^2)思路:这是DP的基础题。最长上升子序列问题(LIS)。先给出O(n^2)的思路和代码。
一开始看到白书上写的“设d[ i ]为以 i 结尾的最长上升子序列长度,则d[ i ] = max(0, d[ j ] | j < i, Aj < Ai) + 1”的时候,简直无爱了。第一不知道这个状转方程是怎么来的,第二不知道那个0是为什么。
然后就上网找代码看。理一下思路,应当是这样的。
首先是初始化,对于每个数字自己作为上升子序列的时候,d[ ]值是1。然后,对于每一个 i,即前 i 个数字枚举每一个 j,首先要符合“上升”条件,符合条件之后,进行状态转移,要怎么转移呢?
每个数字只有一个状态,那就是前 i 个数字能构成的最长上升子序列。这个状态要从前 i-1 个数字能构成的最长上升子序列转移过来吗?然而,不同数字参与构成的最长子序列又不一样,你并不知道哪个会是最优。例如:1、7、3、5、9,看到数字3的时候,7参与的是1、7,3参与的是1、3,看到数字9的时候,1、3、5、9比1、7、9更长。
必须从第一个开始直到第 i 个,每个数字的状态都转移一次,(状转方程)即:
For j: 0 ~ i-1 if(sq[j] < sq[i]) dp[i] = max{dp[i], dp[j] + 1}代码如下:
/****************************************/ #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <cmath> #include <stack> #include <queue> #include <vector> #include <map> #include <string> #include <iostream> using namespace std;/****************************************/int sq[1005], dp[1005];int main(){int n;while(scanf("%d", &n) != EOF) {int ans = 0;for(int i = 0;i < n;i++) {scanf("%d", &sq[i]);dp[i] = 1;for(int j = 0;j < i;j++) {if(sq[j] < sq[i])dp[i] = max(dp[i], dp[j] + 1);}if(ans < dp[i])ans = dp[i];}printf("%d\n", ans);}return 0;}
接下来是期待已久的O(nlogn)的方法。
O(nlogn)思路:
参考大白书的思路,第一种方法其实是有重复劳动的。对于每一个数字 i,都要看前 i 个数是否比它小、从它转移过来是否更优。这种枚举没有注意到子序列中有些数根本不必转移。比如序列1、6、2、3、7,看到数字7的时候,只需要从{1、2、3}转移过来即可,{1、6}这个序列早就该丢弃了。因为对于{1、6}、{1、2}这两个序列,长度一样但是2比6小,这意味着{1、2}将来一定会比{1、6}更优才对。(比6大就一定比2大,比2大却不一定比6大,{1、2}更有可能成为最长)
换句话说,对于相同长度的序列,只需保存Ai最小的,越小越优。
这个时候,我们需要记录当前“最优序列”,这就用到了最优子结构的思想。
怎样记录和更新这个有序的“最优序列”g[ ]呢?二分法。而且应当是二分求下界。(想一想)
初始化g[ ]为无穷大。答案len = 0。接下来枚举数组,每次二分下界,算出“最优序列”个数,更新,然后更新g[ ]。状转方程变成
ans = max{ans, 最优子序列数的个数}
代码如下:
/****************************************/ #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <cmath> #include <stack> #include <queue> #include <vector> #include <map> #include <string> #include <iostream> using namespace std;/****************************************/const int N = 1005, SUP = 2e9;int sq[N], g[N];int main(){int n;while(scanf("%d", &n) != EOF) {for(int i = 1; i <= n; i++) {scanf("%d", &sq[i]);g[i] = SUP;}int len = 0;for(int i = 1;i <= n;i++) {int k = lower_bound(g+1, g+n+1, sq[i]) - g;//下界地址减去g[0]的地址,得到最优序列数的个数len = max(len, k);g[k] = sq[i];}printf("%d\n", len);}return 0;}
- 【DP|LIS】POJ-2533 Longest Ordered Subsequence(O(n^2)、O(nlogn))
- POJ 2533Longest Ordered Subsequence(DP最长上升子序列O(n^2)&&O(nlogn))
- POJ 2533 Longest Ordered Subsequence DP(LIS)
- Longest Ordered Subsequence O(nlogn)解法 STL
- POJ:2533 Longest Ordered Subsequence(LIS-n*logn解法)
- POJ 2533-Longest Ordered Subsequence(DP:LIS)
- POJ 2533 Longest Ordered Subsequence(dp LIS)
- POJ 2533 Longest Ordered Subsequence (DP)【 LIS】
- POJ 2533 Longest Ordered Subsequence(最长上升子序列长度、O(nlogn))
- 每日三题-Day5-A(POJ 2533 Longest Ordered Subsequence 最长上升子序列O(nlogn)解法)
- poj - 2533 - Longest Ordered Subsequence(LIS)
- Poj 2533 Longest Ordered Subsequence(LIS)
- poj 2533 Longest Ordered Subsequence (LIS)
- POJ 2533 Longest Ordered Subsequence (LIS)
- POJ 2533 Longest Ordered Subsequence(LIS)
- POJ 2533 Longest Ordered Subsequence (LIS)
- POJ-2533Longest Ordered Subsequence(LIS)
- POJ 2533 Longest Ordered Subsequence(LIS)
- Likes 4Likes Dislike Creating a Very Simple GUI System for Small Games - Part I
- vs2013 dll 文件的创建和引用
- STAMPS
- Convert Sorted Array to Binary Search Tree
- Coherence(6)在线升级缓存对象
- 【DP|LIS】POJ-2533 Longest Ordered Subsequence(O(n^2)、O(nlogn))
- 自定义hadoop的InputFormat
- 使用CxImage进行图形和格式转换(CBitmap to jpg or png or gif or bmp)
- 软件项目量化管理目标举例
- fork的使用和多次fork产生的一系列问题
- ACM-计算几何之Quoit Design——hdu1007 zoj2107
- 粒子滤波器原理介绍-----本博客部分内容源自西安交大蔡远利教授的随机系统滤波与控制课程讲义
- Autodesk Character Generator
- 忘了