您的位置:首页 > 其它

拦截导弹

2016-06-24 16:03 176 查看

问题描述 Description

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

输入描述 Input Description

第一行为一个整数 N,表示飞来的导弹个数, N≤100000

第二行为 N 个整数,依次表示导弹飞来的高度,高度数据为不大于 30000 的正整数。

输出描述 Output Description

第一行,输出计算这套系统最多能拦截多少导弹

第二行,输出要拦截所有导弹最少要配备多少套这种导弹拦截系统。

输入样例 Sample Input

8

389 207 155 300 299 170 158 65

输出样例 Sample Output

6

2

分析

第一问是求最长不增子序列。

第二问是求最长递增子序列。可以这么想,设最长递增子序列长度为 s,因为拦截 a1 需要使用一套装置, a2>ai ,所以拦截 a2 不能用拦截 a1 的装置,a3>a2>a1 ,所以拦截 a3 不能用拦截 a2,a1 的装置…所以最少要用 s 套装置,可以利用差不多的思路证明最多要用 s 套装置

代码

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

typedef bool(*cmper)(int,int);

int a[100100];
int f[100100];
int n;

void work(cmper);
bool lower(int,int);
bool Super(int,int);
int binary(int,int,int,cmper);

int main(){

scanf("%d",&n);
for(int i=1;i<=n;++i)
scanf("%d",&a[i]);

work(Super);
work(lower);

return 0;

}

void work(cmper cmp1){

f[f[0]=1] = a[1];
for(int i=2;i<=n;++i){
if(cmp1(f[f[0]],a[i]))
f[++f[0]] = a[i];
else if(!cmp1(f[1],a[i]))
f[1] = a[i];
else
f[binary(1,f[0],a[i],cmp1)] = a[i];
}

printf("%d\n",f[0]);

}

bool lower(int a,int b){
return a<b;
}

bool Super(int a,int b){
return a>=b;
}

int binary(int L,int R,int number,cmper cmp){

int M;
while(L+1 < R){
M = (L+R)>>1;
if(f[M] == number){
while(f[M]==number)
++M;
return M;
}
else if(cmp(f[M],number))
L = M;
else
R = M;
}

return R;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: