导弹拦截

本文介绍了一种导弹拦截系统的算法实现,重点在于如何通过贪心算法确定最少的系统数量以拦截所有导弹,以及如何利用动态规划求解单个系统最多能拦截的导弹数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

导弹拦截


直接上题

题目描述

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

输入导弹的枚数和导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数,每个数据之间有一个空格),计算这套系统最多能拦截多少导弹?

如果要拦截所有导弹最少要配备多少套这种导弹拦截系统?

输入格式

第一行数字n表示n个导弹(n<=200) 第二行n个数字,表示n个导弹的高度

输出格式

一个整数,表示最多能拦截的导弹数

一个整数,表示要拦截所有导弹最少要配备的系统数

样例数据

8
389 207 155 300 299 170 158 65

6
2

数据规模与约定

时间限制:1s
空间限制:256MB


解答

从题中可以看出导弹拦截分为两个部分,一个是计算出需要全部拦截下这些导弹的最少系统数,另一个是计算出一套系统最多可以拦截多少导弹;
第一个问题:“需要全部拦截下这些导弹的最少系统数”,用显然法证明是可以用贪心做的,这个样例比较水,在做题目时很有可能就会推出高度为300前面是一组系统,而300(包括300)后是一组,就是简单的推出输入的数据中当前的一个比前一个大,系统就会增加,但这样却是不对的。
虽然当前的高度比以前大确实是有可能要增加系统数,但是前面拦截过的系统还是会有一个值,表示它现在可以拦截的最高的导弹高度,所以需要比较当前的高度是否小于之前的系统的最小值,如果存在,那系统数就不用增加,并且要用之前的系统超出最小的来存当前的值;
第二个问题:“计算出一套系统最多可以拦截多少导弹”就是要计算出最长不上升自序列;根据DP的特性(无后效性),并且每一个导弹都是按照时间顺序来发射的,所以要从后面开始推,从后面开始推,可以用dp[i]数组表示拦截到i的导弹是已经拦截下的导弹,如果第j个导弹比第i个低的话么就说明前面肯定没有拦截到第j个,可以枚举1到i-1个导弹,选一个dp值最大的作为后继
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,a[250],nmax[250],sum=1,dp[250]={};
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
nmax[i]=50000;
}
nmax[sum]=a[1];
for(int i=2;i<=n;i++)
{
bool flag=false;
for(int j=1;j<=sum;j++)
{
if(nmax[j]>=a[i])
{
nmax[j]=a[i],flag=true;
break;
}
}
if(!flag)
{
sum++;
nmax[sum]=a[i];
}
}
dp[1]=1;
for(int i=2;i<=n;i++)
{
for(int j=1;j<=i;j++)
{
if(a[i]<=a[j]&&dp[j]>dp[i]) dp[i]=dp[j];
}
dp[i]++;
}
sort(dp+1,dp+n+1);
cout<<dp[n]<<endl;
cout<<sum;
return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值