码迷,mamicode.com
首页 > 其他好文 > 详细

关于【最长递增子序列(LIS)】

时间:2014-12-19 11:37:53      阅读:115      评论:0      收藏:0      [点我收藏+]

标签:style   blog   ar   io   color   os   sp   for   strong   

拦截导弹

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

 

输入:
每组输入有两行,
第一行,输入雷达捕捉到的敌国导弹的数量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\n",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\n",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",N-(cnt-1));
    }
    return 0;
}
 
/**************************************************************
    Problem: 1131
    User: lcyvino
    Language: C++
    Result: Accepted
    Time:740 ms
    Memory:1020 kb
****************************************************************/

 

关于【最长递增子序列(LIS)】

标签:style   blog   ar   io   color   os   sp   for   strong   

原文地址:http://www.cnblogs.com/Murcielago/p/4173329.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!