ybt1322 拦截导弹

浪尽此生 提交于 2020-02-17 21:58:32

ybt1322 拦截导弹

【题目描述】

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

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

【输入】

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

【输出】

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

【输入样例】

389 207 155 300 299 170 158 65

【输出样例】

2

【提示】

输入:导弹高度:4 3 2

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

【题解】

这道题的思路是令每套装置的价值最大化。

也就是说,避免让一个刚拦截了300m导弹的装置拦截50m的,而刚拦截60m导弹的装置就可以拦截它。

首先,第一发导弹是必须要用一套新的装置的。而第二发就有两种情况:比第一发高,只能再开一套;比第一发矮,使用第一套拦截。到了第i发导弹,就已经有u套装置。那么从小到大枚举装置能拦截的导弹高度,然后选择刚好能拦截i的最小的装置,就能最大限度减小浪费。如果所有装置都无法拦截,那么就新开一个装置来拦截。

关于维护升序排列的装置:由于只有所有装置都无法拦截才会新开装置,所以新装置能拦截的高度一定最高,放在最后是自然的。当由现有的j装置拦截了i导弹,装置j拦截高度更新,由于比j小的所有装置都无法拦截i,所以i的值一定大于1 - j-1,小于j - u的装置,所以j更新后位置不变。

综上所述,贪心策略正确。

代码:

#include<iostream>
#include<cstdio>
using namespace std;
int n, a[1005], f[1005], u=1;
int main() {
    int i = 1;
    while (cin >> a[i]) {//读入数据,直到输入结束为止
        i++;
    }
    f[1] = a[1];//使用新的装置拦截第一个导弹
    for (int j = 1; j <= i; j++) {//枚举每个导弹
        bool flag=0;//记录是否被拦截
        for (int k = 1; k <= u; k++) {//枚举用哪个装置
            if (f[k] >= a[j]) {//能拦截的第一套装置
                f[k] = a[j];//更新装置
                flag = 1;//打标记
                break;//停止枚举
            }
        }
        if (!(flag)) {//无法拦截,新建装置
            f[++u] = a[j];//放在最后
        }
    }
    cout << u << endl;//输出装置数量
    return 0;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!