拦截导弹,动规贪心是朋友你知道吗!

§缘
可能有些人,还记得18年前(1999)年NOIP的一道水题:拦截导弹。

题目描述某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。 输入导弹依次飞来的高度,计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
输入:第1行:依次输入若干个导弹的高度H(1≤H≤30000),导弹的个数N≤5000
输出:第1行:一个整数,表示单枚炮弹能拦截多少导弹 第2行:一个整数,表示拦截所有导弹最少要配备多少套这种导弹拦截系统
样例输入389 207 155 300 299 170 158 65
样例输出6 2
§思
显然,这道题要分为两部分,第一部分就是用动态规划求一个最长不上升子序列,
第二部分就用贪心,每次要让拦截导弹的系统损耗(若他能够打下A,但最终去用来打B,称A-B为他的损耗)最低,若无法拦截,则新增一套系统。
于是就有了:
§解

#include<cstdio>
int a[2][5001],n,m,af=1,Max[5001],ans,Min,Minx;
int main()
{
    while(scanf("%d",&a[0][++n])!=EOF);
    n--;
    for(int i=1;i<=n;i++)a[1][i]=1;
    for(int i=n-1;i>=1;i--)
    {
        m=0;
        for(int j=i+1;j<=n;j++)if(a[0][j]<=a[0][i]&&a[1][j]>m)m=a[1][j];
        if(!m)continue;
        a[1][i]=m+1;
    }
    for(int i=2;i<=n;i++)if(a[1][i]>a[1][af])af=i;
    printf("%d\n",a[1][af]);
    for(int i=1;i<=n;i++)
    {
        Min=50000;
        for(int j=1;j<=ans;j++)if(Min>Max[j]&&Max[j]>=a[0][i])Min=Max[j],Minx=j;
        if(Min==50000)ans++,Max[ans]=a[0][i];
        else Max[Minx]=a[0][i];
    }
    printf("%d",ans);
}

§优
首先,某同学说他可以不要命他认为可以不用MIN,然后真的就不要MIN了,然后任然AC,于是我就仔细思考了一下,事实上是因为我的MAX数组最终的结果一定是有序的,所以要不要MIN其实是一样的,然后由此推出,此题的第二问,可以直接求一个最长上升序列,他的长度就是答案,显然,这是对的,稍微动动脑袋就可以知道,而具体代码,这里就不给出了,要给读者思考的空间233~~。
§结
所以虽然标题是“贪心动规”,但这题只用动规也能做出来!

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值