导弹拦截HDU1275

题意

就是给出一个序列,然后找出最少数量的非递增序列,按照题目的意思,每一个非递增的序列就是一个拦截系统。

题解

来自洛谷的一位大佬
假设现在有k套拦截系统,目前每套系统的拦截高度为dp[i],(1<=i<=k),那么现在要用这几套系统拦截另外一个高度为h的导弹p,则必须满足条件 m a x 1 < = i < = k ( d p [ i ] ) > h max_{1<=i<=k}(dp[i]) > h max1<=i<=k(dp[i])>h,换句话说就是这几个方案中必须存在方案能使得高度为h的导弹p被拦截,就是说dp[i]中必须有一个值比h大,如果可以拦截呢,那么必须要让那个dp值最接近h且比h大的拦截系统进行拦截(这句话是没有证明的,我们再后面进行说明),于是按照这样的思路有如下代码:

ps:

那么必须要让那个dp值最接近h且比h大的拦截系统进行拦截
这句话实际上没有证明这样的算法是最优的,我们可以很轻松的证明出来如果一定要用以往的方案进行拦截的话(我没有办法证明不用以往的方案,也就是新开辟一个方案一定不是最优的!如果有人会的话可以和我交流以下!!),那么使用dp值比h大且最接仅的方案一定是最优秀的,如下图所所示。在这里插入图片描述
我们把每个方案拿出来,dpi就是方案i可以接受的最大导弹高度,假设现在有一个高度为h的导弹,那么方案3,4,5可以将导弹拦截,我们可以发现,使用不同方案拦截后损失的可拦截高度时不一样的,比如用方案3拦截,损失高度为[h,dp3],也就是说,这个区间的导弹会少拦截一颗(不是不能拦截,因为其他方案还可以拦截这个高度的导弹,值不过会少拦截一颗),使用方案4拦截,损失高度为[h,dp4],这个区间会少拦截一颗导弹,相比于在[h,dp3]区间少拦截一颗导弹,使用方案4还会多出一段[h3,h4]区间少拦截一颗导弹,这是不合适的,使用方案5同理,所以要选择且最大拦截值dp离h最近且比h大的方案。

// 题解https://www.luogu.com.cn/problem/solution/P1020

// #include<bits/stdc++.h>
#include<iostream>

using namespace std;

const int maxx = 2000 + 5;
int shell[maxx];
int dp[maxx];   // 表示第k套拦截系统的最小值

int find(int k,int val)     // 假设我们现在有k套系统。
{
    int l = 0, r = k - 1;
    while(l<r){     // l == r break; l和r中恰好有val的上限
        int mid = (l + r)>>1;
        if(dp[mid] < val){
            l = mid + 1;
        }
        else {
            r = mid;
        }
    }   // dp[r] >= val
    if(dp[r] < val) r = r + 1;     // 添加下一个系统
    return r;
}

int main()
{
    int n;
    int ans;
    while(scanf("%d",&n) == 1){
        for(int i=0;i<n;i++)scanf("%d",&shell[i]);
        if(n == 0){
            cout<<0<<endl;
            continue;
        }
        ans = 1;
        dp[0] = shell[0];
        for(int i = 1; i < n; i++){
            int posi = find(ans, shell[i]);
            if(posi == ans)ans++;
            dp[posi] = shell[i];
        }
        cout<<ans<<endl;
    }
    return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值