寒假练习 1012 导弹防御问题

    这题题目大意很清楚,之所以一开始没做是因为理解出错。

    因为导弹不能上升,所以: 

    第一个要求是求出某枚导弹的最多拦截个数,这个很好理解,就是求解不上升的最长子序列

    第二个要求是求出最少的拦截导弹个数,因为一枚导弹发射出去后就不能上升,所以要求出需要多少枚导弹,就是求出最长上升子序列,相当于敌机是一架一架的来, 一枚导弹一经发射就不可能后退或者上升,所以为对付后来的上升的飞机,就必须重新发射一枚导弹(一开始理解错了,以为要找出最少的能覆盖整个序列的几个上升的子序列)   

    还有就是这种算法是 N * logN的算法,好好理解下,至于O(n^2)的算法就不说了。。。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define inf 999999
#define maxn 100006

int num[maxn];
int dp[maxn];  //dp[i]表示以num[i]尾的最长子序列 
int len;
int find_up(int L,int R,int x)  //上升子序列的函数 
{
    if(L==R) return L;
    int mid = (L+R)>>1;
    if(dp[mid]<x) return find_up(mid+1,len,x);
    else return find_up(L,mid,x);
}
int find_down(int L,int R,int x) //下降子序列的函数 
{
    if(L==R) return L;
    int mid = (L+R)>>1;
    if(dp[mid]>=x) return find_down(mid+1,len,x);
    else return find_down(L,mid,x);
}
int main()
{
    int n,j;
    
    while(~scanf("%d",&n))
    {
        for(int i=0;i<n;i++)
            scanf("%d",&num[i]);
        //--------------------------------------
        //以下是求解最长不上升子序列 
        len = 0;
        dp[0] = inf;
        
        for(int i=0;i<n;i++)
        {
            if(num[i] <= dp[len]) j = ++len;
            else j = find_down(1,len,num[i]);
            
            dp[j] = num[i];
        }
        printf("%d ",len);
        
        //---------------------------------------
        //以下是求解最长上升子序列 
        len = 0;
        dp[0] = -inf;
        
        for(int i=0;i<n;i++)
        {
            if(num[i] > dp[len]) j = ++len;
            else j = find_up(1,len,num[i]);
            
            dp[j] = num[i];
        }
        printf("%d\n",len);
    }
    
    return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值