zoukankan      html  css  js  c++  java
  • POJ-2533最长上升子序列(DP+二分)(优化版)

    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 (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
    

    Source

    Northeastern Europe 2002, Far-Eastern Subregion
     
    方法一:记忆化搜索
    缺点:时间复杂度O(n^2)
    #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 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
    ", dfs(n-1)+ 1);
                printf("%d
    ", pp);
        }
        return 0;
    }

    方法二:dp+二分

    其中low_bound 返回第一个大于它的数的下标。

    缺点:无法保存每个以 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 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;
                    dp[pos] = a[i];
                }
            }
            printf("%d
    ", cnt+1);
        }
    
        return 0;
    }

    方法三:dp+二分(优化版)

    弥补了上面两种方法不足。时间复杂度为O(nlogn) 又能保存每个以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
    ", ans);
        }
    
        return 0;
    }
  • 相关阅读:
    Thymeleaf学习记录(6)--迭代及条件语法
    Thymeleaf学习记录(5)--运算及表单
    Thymeleaf学习记录(4)--$/*/#/@语法
    Thymeleaf学习记录(3)--语法
    Thymeleaf学习记录(2)--自动编译设置
    ssh和scp详解
    持续集成(Continuous integration)
    部署基于python语言的WEB发布环境
    python垃圾回收机制(Garbage collection)
    Dockerfile定制镜像
  • 原文地址:https://www.cnblogs.com/ZP-Better/p/5136497.html
Copyright © 2011-2022 走看看