1. 程式人生 > >【POJ - 2533】Longest Ordered Subsequence(四種方法解決最長上升子序列 含二分優化版本)

【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 (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;
}