导弹拦截(O(nlogn)的做法)

文章讨论了一种导弹拦截系统,其特点是后续导弹拦截高度不能超过前一发。通过寻找最长上升子序列的长度,可以确定最少需要的导弹拦截系统数量。同时,通过调整策略,寻找最长不上升子序列,可计算系统能拦截的最多导弹数。文中提供了C++代码实现。
摘要由CSDN通过智能技术生成

题目描述

某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。

输入导弹依次飞来的高度,计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

输入格式

一行,若干个整数,中间由空格隔开。

输出格式

两行,每行一个整数,第一个数字表示这套系统最多能拦截多少导弹,第二个数字表示如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

思路

1.最少要配备多少套这种导弹拦截系统:

此题要求我们把数组划分成几个不上升子序列,求不上升子序列的最少个数.由偏序的相关知识我们可以证明出不上升子序列的最少个数即等于最长上升子序列的长度.
如果直接用dp,解法易想也方便,但dp的时间复杂度是O(n*n),不符合要求
那么我们再尝试在模拟的过程中寻找可优化的地方.
可以采用一个数组来存储各个已配置导弹拦截系统目前能有的最高拦截高度(由小到大存储),每次新读入的高度x若大于数组中最大的元素,则再增加一套拦截系统,否则找到数组中第一个大于等于x的元素,给它重新赋值为x(贪心法),表示对应的导弹拦截系统拦截高度降为x.遍历完数组后最长上升子序列也就构造完成

2.这套系统最多能拦截多少导弹

不难知道这一问其实就是求最长不上升子序列长度,它可以看作是求解最长上升子序列的相反过程再微改条件的结果(上升->下降->不上升),代码内容和其大体一致,稍作更改即可

代码

#include <iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
int x,f[100005],i,g[100005],j,a[100005],k=1;
int main()
{
    while(cin>>x) {
        //求最长上升子序列
        if (x > f[i]) f[++i] = x;
        else *lower_bound(f+1, f + i+1, x) = x; 
        //求最长不上升子序列
        if (x <= g[k]) g[++k] = x;
        else *upper_bound(g + 1, g + k+1, x,greater<int>()) = x; //这里注意要使用greater
    }
    cout << k <<endl<<i;
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值