信息学奥赛一本通题目解析:1322:【例6.4】拦截导弹问题(Noip1999)

【题目描述】

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

输入导弹依次飞来的高度(雷达给出的高度不大于30000的正整数)。计算要拦截所有导弹最小需要配备多少套这种导弹拦截系统。

【输入】

n颗依次飞来的高度(1≤n≤1000)。

【输出】

要拦截所有导弹最小配备的系统数k。

【输入样例】

389 207 155 300 299 170 158 65

【输出样例】

2

【提示】

输入:导弹高度: 4  3  2

输出:导弹拦截系统k=1

【解题思路】

  • 用贪心的思想,在尽可能少的拦截系统中分配导弹,始终尝试将新的导弹分配给已有的能拦截它的系统,而不是贸然开设新系统。
  • 当一个系统被更新以拦截一个新的导弹时,它的“最大高度”降低了,这反映了一旦拦截了更低高度的导弹,系统的使用条件就变得更加严格了。
  • 如果没有现有系统能拦截新来的导弹,这意味着必须增设新的系统,因此算法的贪心性质在于它总是尝试以最低的成本(即最少的系统数量)来满足新的需求。

代码思路

  1. 初始化存储结构:使用一个vector<int> v来存储每套拦截系统能够拦截的最大高度。这里,“最大高度”实际上表示该系统可以拦截的当前最低高度的导弹,因为一旦拦截了某个高度的导弹,该系统就不能拦截更高的导弹了。

  2. 读取导弹高度:通过一个while循环不断读入导弹的高度n

  3. 尝试拦截导弹:对于每颗导弹,代码遍历当前所有的拦截系统(由vector v表示),寻找是否存在一个系统能够拦截该导弹。这是通过检查v[i] >= n来完成的,即当前系统能拦截的最大高度(实际上是最低高度的导弹)是否大于等于当前导弹的高度。

    • 如果找到这样的系统,就将该系统的拦截高度更新为当前导弹的高度(v[i] = n),因为该系统现在的最大拦截高度就是这颗导弹的高度。
    • 如果没有找到能够拦截当前导弹的系统,就需要新建一套拦截系统,这通过v.push_back(n)实现,即添加一个新的元素到vector中,表示这个新系统的当前最大拦截高度。
  4. 输出结果:最后,输出vector v的大小(v.size()),这表示了最小需要配备的拦截系统数量,因为vector中的每个元素都代表了一套能够拦截至少一颗导弹的系统。

【代码实现】

#include <iostream>
#include <vector>
using namespace std;
int main() {
    int n;
    vector<int> v; // 存储每套拦截系统能够拦截的最大高度
    while (cin >> n) {
        bool flag = false; // 标记是否找到能够拦截当前导弹的拦截系统
        for (int i = 0; i < v.size(); i++) {
            if (v[i] >= n) { // 找到了能够拦截当前导弹的拦截系统
                v[i] = n; // 更新这个拦截系统能够拦截的最大高度
                flag = true;
                break;
            }
        }
        if (!flag) { // 没有找到能够拦截当前导弹的拦截系统
            v.push_back(n); // 新建一套拦截系统
        }
    }
    cout << v.size() << endl; // 输出答案
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值