问题描述:
某国为了防御敌国的导弹袭击,开发出一种导弹拦截系统,但是这种拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭,由于该系统还在试用阶段。所以一套系统有可能不能拦截所有的导弹。
输入导弹依次飞来的高度(雷达给出的高度不大于30000的正整数)。计算要拦截所有导弹最小需要配备多少套这种导弹拦截系统。
输入:
n颗依次飞来的高度(1≤n≤1000)。
输出:
要拦截所有导弹最小配备的系统数k。
输入样例:
389 207 155 300 299 170 158 65
输出样例:
2
自己挖坑自己填,刺激.jpg
(挖坑)最初思路:“由于每次只有出现高于上一个导弹高度的导弹出现时,就会来判断是否增加拦截系统”,所以先遍历一遍将出现n[i] <n[i+1]的两个高度分别存到数组a和数组b同时拦截系统数k加一。然后依次将b数组的值(b[i)]与之前的a数组的值(a[1]~a[i-1])相比较,选出大于等于b[i]且最小的a[m](也就是最接近b[i]数值的a[m]),如果a[m]存在则拦截系统数k减一,同时令a[m]为零,相当于该系统的最低高度在为a[i+1],否则不操作。
#include<iostream>//对于赋有双重含义的变量需注意变量在一种含义下变化了,另一种情况里的该变量会受影响。
#include<cstdio>
using namespace std;
int main()
{
int n[1001], a[1001], b[1001];
int t, i = 0, k = 1;
while(scanf("%d", &t) == 1)
n[i++] = t;
int z = 0;
for(int j = 0; j < i-1; j++)
{
if(n[j] < n[j+1])
{
k++;
a[z] = n[j];
b[z++] = n[j+1];
}
}
bool flag;
int min, c, key;
for(int j = 1; j < z; j++)
{
flag = false;
min = 30001;
for(int m = 0; m < j; m++)
{
if(b[j] <= a[m])
{
flag = true;
c = a[m] - b[j];
if(c < min)
{
min = c;
key = m;
}
}
}
if(flag == true)
{
k--;
a[key] = 0;
}
}
cout << k;
return 0;
}
submit -> 70分,T-T
最后找到了corner case:10 9 8 10 7 6 9 -> 2
判断是否增加系统不仅仅是在出现递增数对处,每枚导弹高度都会影响增减系统,上面case中,两个系统分别拦截的高度是k1[10 9 8 7 6] k2[10 9]
所以最初遇递增存a,b数组的方法是错误的。
正确解法:l[1]存n[0]初设为第一套系统的可拦截最大高度,依次对后面到来的导弹进行判断,若高于前面所有系统的可拦截的最高高度,则系统数加一,并令新增系统的最大拦截高度为当前导弹高度,否则在前面所有拦截高度高于当前导弹高度的系统中选择拦截高度最低的系统,令其最大拦截高度为当前导弹高度。
#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
int n[1001], l[1001], t = 0, k = 1, temp;
while(scanf("%d", &temp) == 1)
n[t++] = temp;
l[1] = n[0];
int p;
for(int i = 1; i < t; i++)
{
p = 0;
for(int j = 1; j <= k; j++)
{
if(n[i] <= l[j])
{
if(p == 0)
p = j;
else if(l[j] < l[p])
p = j;
}
}
if(p == 0)
l[++k] = n[i];
else
l[p] = n[i];
}
cout << k;
}