0
点赞
收藏
分享

微信扫一扫

【POJ - 2533】Longest Ordered Subsequence(四种方法解决最长上升子序列 含二分优化版本)

新鲜小饼干 2022-06-15 阅读 17

题干:

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 (a1a2, ..., aN) be any sequence (ai1ai2, ..., 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 8

Sample 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 1100

int 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: (二分优化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 11000

int 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;//其实应该是upperbound,但是这里不会有重复的数字,所以也可以用lowerbound + 1去做。因为这里dp下标从0开始的所以这样写的话pos相当于位置 + 1了。所以这样写也是正确的。
dp[pos] = a[i];
}
}
printf("%d\n", cnt+1);
}

return 0;
}

AC代码4:(最优版本,可以保留以a[i]为结尾的子序列)

#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 11000

int 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;
}

 

 


举报

相关推荐

最长上升子序列优化

0 条评论