zoukankan      html  css  js  c++  java
  • 关于【最长递增子序列(LIS)】

    拦截导弹

    题目描述:
    某国为了防御敌国的导弹袭击,开发出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭,并观测到导弹依次飞来的高度,请计算这套系统最多能拦截多少导弹。拦截来袭导弹时,必须按来袭导弹袭击的时间顺序,不允许先拦截后面的导弹,再拦截前面的导弹。 
     
    输入:
    每组输入有两行,
    第一行,输入雷达捕捉到的敌国导弹的数量k(k<=25),

    第二行,输入k个正整数,表示k枚导弹的高度,按来袭导弹的袭击时间顺序给出,以空格分隔。

    输出:
    每组输出只有一行,包含一个整数,表示最多能拦截多少枚导弹。
     
    样例输入:
    8
    300 207 155 300 299 170 158 65
    样例输出:
    6

    Code:
    #include <cstdio>
     
    using namespace std;
     
    int maxVal(int a,int b){
        return a>b?a:b;
    }
     
    int main()
    {
        const int arrSize=30;
        int arr[arrSize];
        int dp[arrSize];
        int n;
        while(scanf("%d",&n)!=EOF){
            for(int i=1;i<=n;++i){
                scanf("%d",&arr[i]);
                dp[i]=0;
            }
            for(int i=1;i<=n;++i){
                int tmax=1;
                for(int j=1;j<i;++j){
                    if(arr[j]>=arr[i])
                        tmax=maxVal(tmax,dp[j]+1);
                }
                dp[i]=tmax;
            }
            int cnt=dp[1];
            for(int i=1;i<=n;++i){
                if(dp[i]>cnt)
                    cnt=dp[i];
            }
            printf("%d
    ",cnt);
        }
        return 0;
    }
     
    /**************************************************************
        Problem: 1112
        User: lcyvino
        Language: C++
        Result: Accepted
        Time:0 ms
        Memory:1020 kb
    ****************************************************************/

     

     最大序列和

    题目描述:

    给出一个整数序列S,其中有N个数,定义其中一个非空连续子序列T中所有数的和为T的“序列和”。
    对于S的所有非空连续子序列T,求最大的序列和。
    变量条件:N为正整数,N≤1000000,结果序列和在范围(-2^63,2^63-1)以内。
     

    输入:

    第一行为一个正整数N,第二行为N个整数,表示序列中的数。

    输出:

    输入可能包括多组数据,对于每一组输入数据,
    仅输出一个数,表示最大序列和。

    样例输入:
    5
    1 5 -3 2 4
    
    6
    1 -2 3 4 -10 6
    
    4
    -3 -1 -2 -5
    样例输出:
    9
    7
    -1

    Code:
    #include <cstdio>
     
    using namespace std;
     
    const int arrSize=1000010;
    long long arr[arrSize];
    long long dp[arrSize];
     
    int main()
    {
       int N;
       while(scanf("%d",&N)!=EOF){
            for(int i=1;i<=N;++i){
                scanf("%lld",&arr[i]);
                dp[i]=0;
            }
            for(int i=1;i<=N;++i){
                long long tmax=arr[i];
                if(i>1){
                    if(dp[i-1]>0){
                        dp[i]=dp[i-1]+arr[i];
                        continue;
                    }
                }
                dp[i]=tmax;
            }
            long long result=dp[1];
            for(int i=1;i<=N;++i){
                if(dp[i]>result)
                    result=dp[i];
            }
            printf("%lld
    ",result);
       }
       return 0;
    }
     
    /**************************************************************
        Problem: 1077
        User: lcyvino
        Language: C++
        Result: Accepted
        Time:120 ms
        Memory:16644 kb
    ****************************************************************/

     

     

    合唱队形

    题目描述:

    N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学不交换位置就能排成合唱队形。
    合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1, 2, …, K,他们的身高分别为T1, T2, …, TK,
    则他们的身高满足T1 < T2 < … < Ti , Ti > Ti+1 > … > TK (1 <= i <= K)。
    你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。

    输入:

    输入的第一行是一个整数N(2 <= N <= 100),表示同学的总数。
    第一行有n个整数,用空格分隔,第i个整数Ti(130 <= Ti <= 230)是第i位同学的身高(厘米)。

    输出:

    可能包括多组测试数据,对于每组数据,
    输出包括一行,这一行只包含一个整数,就是最少需要几位同学出列。

    样例输入:
    8
    186 186 150 200 160 130 197 220
    样例输出:
    4

    Code:
    #include <cstdio>
     
    using namespace std;
     
    int maxVal(int a,int b){
        return a>b?a:b;
    }
     
    int main()
    {
        const int arrSize=110;
        int arr[arrSize];
        int dpUp[arrSize];
        int dpDown[arrSize];
        int N;
        while(scanf("%d",&N)!=EOF){
            for(int i=1;i<=N;++i){
                scanf("%d",&arr[i]);
                dpUp[i]=0;
                dpDown[i]=0;
            }
            for(int i=1;i<=N;++i){    //正向运用LIS
                int tmax=1;
                for(int j=1;j<i;++j){
                    if(arr[j]<arr[i])
                        tmax=maxVal(tmax,dpUp[j]+1);
                }
                dpUp[i]=tmax;
            }
            for(int i=N;i>=1;--i){   //反向运用LIS
                int tmax=1;
                for(int j=N;j>i;--j){
                    if(arr[j]<arr[i])
                        tmax=maxVal(tmax,dpDown[j]+1);
                }
                dpDown[i]=tmax;
            }
            int cnt=dpUp[1]+dpDown[1];
            for(int i=1;i<=N;++i){
                if(dpUp[i]+dpDown[i]>cnt)
                    cnt=dpUp[i]+dpDown[i];
            }
            printf("%d
    ",N-(cnt-1));
        }
        return 0;
    }
     
    /**************************************************************
        Problem: 1131
        User: lcyvino
        Language: C++
        Result: Accepted
        Time:740 ms
        Memory:1020 kb
    ****************************************************************/

    最大连续子序列

    题目描述:
        给定K个整数的序列{ N1, N2, ..., NK },其任意连续子序列可表示为{ Ni, Ni+1, ..., Nj },其中 1 <= i <= j <= K。最大连续子序列是所有连续子序列中元素和最大的一个,例如给定序列{ -2, 11, -4, 13, -5, -2 },其最大连续子序列为{ 11, -4, 13 },最大和为20。现在增加一个要求,即还需要输出该子序列的第一个和最后一个元素。
    输入:

        测试输入包含若干测试用例,每个测试用例占2行,第1行给出正整数K( K< 10000 ),第2行给出K个整数,中间用空格分隔。当K为0时,输入结束,该用例不被处理。

    输出:

        对每个测试用例,在1行里输出最大和、最大连续子序列的第一个和最后一个元素,中间用空格分隔。如果最大连续子序列不唯一,则输出序号i和j最小的那个(如输入样例的第2、3组)。若所有K个元素都是负数,则定义其最大和为0,输出整个序列的首尾元素。

    样例输入:
    6
    -2 11 -4 13 -5 -2
    10
    -10 1 2 3 4 -5 -23 3 7 -21
    6
    5 -8 3 2 5 0
    1
    10
    3
    -1 -5 -2
    3
    -1 0 -2
    0
    样例输出:
    20 11 13
    10 1 4
    10 3 5
    10 10 10
    0 -1 -2
    0 0 0

    Code:
    #include <cstdio>
     
    using namespace std;
     
    struct Status{
        int sum;
        int first;
        int last;
    };
     
    int main()
    {
        int n;
        int arr[10010];
        Status dp[10010];
        while(scanf("%d",&n)!=EOF){
            if(n==0)
                break;
            for(int i=1;i<=n;++i){
                scanf("%d",&arr[i]);
                dp[i].sum=dp[i].first=dp[i].last=0;
            }
            bool isAllNeg=true;
            for(int i=1;i<=n;++i){
                if(arr[i]>=0){
                    isAllNeg=false;
                    break;
                }
            }
            if(isAllNeg){
                printf("%d %d %d
    ",0,arr[1],arr[n]);
                continue;
            }
            dp[1].sum=arr[1];
            dp[1].first=dp[1].last=arr[1];
            for(int i=2;i<=n;++i){
                if(arr[i]+dp[i-1].sum>arr[i]){
                    dp[i].sum=arr[i]+dp[i-1].sum;
                    dp[i].first=dp[i-1].first;
                    dp[i].last=arr[i];
                }else{
                    dp[i].sum=arr[i];
                    dp[i].first=arr[i];
                    dp[i].last=arr[i];
                }
            }
            int maxSum=0;
            for(int i=0;i<=n;++i){
                if(dp[i].sum>maxSum)
                    maxSum=dp[i].sum;
            }
            for(int i=1;i<=n;++i){
                if(dp[i].sum==maxSum){
                    printf("%d %d %d
    ",dp[i].sum,dp[i].first,dp[i].last);
                    break;
                }
            }
        }
        return 0;
    }
     
    /**************************************************************
        Problem: 1011
        User: lcyvino
        Language: C++
        Result: Accepted
        Time:20 ms
        Memory:1104 kb
    ****************************************************************/
  • 相关阅读:
    极验滑动验证码
    保利威视频播放
    Redis
    DRF 解析器和渲染器
    DRF 分页组件
    DRF 权限和频率
    Nginx反向代理
    Laravel使用反向migrate 和 iseed扩展导出表数据
    psr规范发展历程
    supervisor
  • 原文地址:https://www.cnblogs.com/Murcielago/p/4173329.html
Copyright © 2011-2022 走看看