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; }
来源:https://www.cnblogs.com/Wild-Donkey/p/12323370.html