【POJ - 2533】Longest Ordered Subsequence(四种方法解决最长上升子序列 含二分优化版本)
題干:
| Time Limit:?2000MS | ? | Memory Limit:?65536K |
| Total Submissions:?41944 | ? | Accepted:?18453 |
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.
Input
The first line of input file contains the length of sequence N. The second line contains the elements of sequence - N integers in the range from 0 to 10000 each, separated by spaces. 1 <= N <= 1000
Output
Output file must contain a single integer - the length of the longest ordered subsequence of the given sequence.
Sample Input
7 1 7 3 5 9 4 8Sample Output
4解題報告:
?
?
AC代碼1:(記憶化搜索版o(n^2) )
#include <cstdio> #include <iostream> #include <algorithm> #include <cmath> #include <cstring> using namespace std;const int INF=0x3f3f3f3f; const double eps=1e-10; const double PI=acos(-1.0); #define maxn 1100int a[maxn]; int dp[maxn]; int dfs(int p) {if(dp[p] != -1) return dp[p];int res = 0;for(int i = 0; i < p; i++)if(a[p] > a[i])res = max(res, dfs(i)+1);dp[p] = res;return res; } int main() {int n;while(~scanf("%d", &n)){memset(dp, -1, sizeof dp);for(int i = 0; i < n; i++)scanf("%d", &a[i]);int pp = -1;for(int j = 0; j < n; j++){pp = max(pp, dfs(j)+1);}//printf("%d\n", dfs(n-1)+ 1);printf("%d\n", pp);}return 0; }AC代碼2:(直接遞推版o(n^2))
#include<iostream> #define ll long long using namespace std; const int MAX = 1000 + 5; int n; ll a[MAX]; ll dp[MAX]; int main() {cin>>n;for(int i = 1; i<=n; i++) {cin>>a[i];}for(int i = 1; i<=n; i++) dp[i] = 1;for(int i = 1; i<=n; i++) {for(int j = 1; j<i; j++) {if(a[i] > a[j])dp[i] = max(dp[i],dp[j] + 1);}}ll maxx = dp[1];for(int i = 1; i<=n; i++) {maxx = max(maxx,dp[i]);}cout << maxx << endl;return 0 ; }AC代碼3: (二分優(yōu)化nlogn版本,缺點在于沒有丟失了真實的輸入順序,比如樣例: 2 5 1)
#include <cstdio> #include <iostream> #include <cstdlib> #include <algorithm> #include <ctime> #include <cmath> #include <string> #include <cstring> #include <stack> #include <queue> #include <list> #include <vector> #include <map> #include <set> using namespace std;const int INF=0x3f3f3f3f; const double eps=1e-10; const double PI=acos(-1.0); #define maxn 11000int a[maxn]; int dp[maxn]; int main() {int n;while(~scanf("%d", &n)){for(int i = 0; i < n; i++)scanf("%d", &a[i]);int cnt = 0;//memset(dp, INF, sizeof dp);dp[cnt] = a[0];for(int i = 1; i < n; i++){if(a[i] > dp[cnt]){dp[++cnt] = a[i];}else{int pos = lower_bound(dp,dp+cnt+1,a[i]) - dp;//其實應(yīng)該是upperbound,但是這里不會有重復(fù)的數(shù)字,所以也可以用lowerbound + 1去做。因為這里dp下標(biāo)從0開始的所以這樣寫的話pos相當(dāng)于位置 + 1了。所以這樣寫也是正確的。dp[pos] = a[i];}}printf("%d\n", cnt+1);}return 0; }AC代碼4:(最優(yōu)版本,可以保留以a[i]為結(jié)尾的子序列)
#include <cstdio> #include <iostream> #include <cstdlib> #include <algorithm> #include <ctime> #include <cmath> #include <string> #include <cstring> #include <stack> #include <queue> #include <list> #include <vector> #include <map> #include <set> using namespace std;const int INF=0x3f3f3f3f; const double eps=1e-10; const double PI=acos(-1.0); #define maxn 11000int a[maxn]; int b[maxn]; int dp[maxn]; int main() {int n;while(~scanf("%d", &n)){for(int i = 0; i < n; i++)scanf("%d", &a[i]);memset(dp, 0, sizeof dp);memset(b, INF, sizeof b);for(int i = 0; i < n; i++){int pos = lower_bound(b,b+n,a[i]) - b;dp[i] = pos+1;b[pos] = a[i];}int ans = -1;for(int i = 0; i < n; i++)ans = max(ans, dp[i]);printf("%d\n", ans);}return 0; }?
?
總結(jié)
以上是生活随笔為你收集整理的【POJ - 2533】Longest Ordered Subsequence(四种方法解决最长上升子序列 含二分优化版本)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 两大揽储利器被断后,中小银行再搬出花式揽
- 下一篇: 拉格朗日差值 - 杜教板子