算法训练 拦截导弹
时间限制:1.0s 内存限制:256.0MB
问题描述
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
输入格式
一行,为导弹依次飞来的高度
输出格式
两行,分别是最多能拦截的导弹数与要拦截所有导弹最少要配备的系统数
样例输入
389 207 155 300 299 170 158 65
样例输出
6
2
题意: 略
分析: 感觉这道题很巧妙的将这两个看似相同的算法结合在了一起,一个是最长非下降子序列问题,另一个是最长上升子序列问题,考虑下题意,问的是最少要配备的系统数,说白了就是看你能找几条“最长非上升子序列”,将序列倒置下就换成求最长非下降子序列,这里求得条数,恰好就是最长上升子序列的最大个数,自己模拟下即可
N^2写法
#include <bits/stdc++.h>
using namespace std;
int a[10010];
int len,res;
int up[10010],down[10010];
int main() {
string s;
getline(cin,s);
istringstream ss(s);
int x;
while(ss >> x) a[len++] = x;
int res_num = 0,res_cnt = 0;
for(int i = 0;i < len;i++) {
up[i] = down[i] = 1;
for(int j = 0;j < i;j++) {
if(a[i] <= a[j])
down[i] = max(down[i],down[j] + 1);
else {
up[i] = max(up[i],up[j] + 1);
}
}
res_cnt = max(res_cnt,up[i]);
res_num = max(res_num,down[i]);
}
cout<<res_num<<endl<<res_cnt<<endl;
return 0;
}
nlogn写法
#include <bits/stdc++.h>
using namespace std;
int a[10010];
int b[10010];
int len1,len2,len;
int up[10010],down[10010];
int main() {
string s;
getline(cin,s);
istringstream ss(s);
int x;
while(ss >> x) a[len++] = x;
for(int i = len-1;i >= 0;i--) b[len-i-1] = a[i];
up[0] = a[0];
for(int i = 1;i < len;i++) {
if(a[i] > up[len1]) {
up[++len1] = a[i];
} else {
int t = lower_bound(up,up + len1,a[i]) - up;
up[t] = a[i];
}
}
down[0] = b[0];
for(int i = 1;i < len;i++) {
if(b[i] >= down[len2]) {
down[++len2] = b[i];
} else {
int t = upper_bound(down,down + len2,b[i]) - down;
down[t] = b[i];
}
}
cout<<len2+1<<endl<<len1+1<<endl;
return 0;
}
- 如有错误或遗漏,请私聊下UP,ths