(HDU 1259) 最少拦截系统 dp || 贪心

来源:互联网 发布:mac软件安装文件夹 编辑:程序博客网 时间:2024/05/22 01:52

最少拦截系统
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 35285 Accepted Submission(s): 13963

Problem Description
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能超过前一发的高度.某天,雷达捕捉到敌国的导弹来袭.由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹.
怎么办呢?多搞几套系统呗!你说说倒蛮容易,成本呢?成本是个大问题啊.所以俺就到这里来求救了,请帮助计算一下最少需要多少套拦截系统.

Input
输入若干组数据.每组数据包括:导弹总个数(正整数),导弹依此飞来的高度(雷达给出的高度数据是不大于30000的正整数,用空格分隔)

Output
对应每组数据输出拦截所有导弹最少要配备多少套这种导弹拦截系统.

Sample Input
8 389 207 155 300 299 170 158 65

Sample Output
2

Source
浙江工业大学第四届大学生程序设计竞赛

Recommend
JGShining

分析:
这是一道求最长非递增子序列的问题。之前我们就已经做过这类问题了,dp O(n^2),或者 O(nlogn)
我们可以经过多次求得答案。

那么我们那否一次性求出答案呢?但是可以的
设dp[i] 表示第i个系统目前所能拦截的最大的高度,所以当一个导弹到达时,我们遍历一下所有的系统,若有系统可以拦截,则该直接拦截并更新可拦截高度,否则若所有的都无法拦截,则新加一个系统。
时间复杂度 : O(n^2)
代码:

#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <algorithm>#include <cmath>using namespace std;const int maxn = 1000000;int dp[maxn];int ans,n,x;int main(){    while(scanf("%d",&n)!=EOF)    {        dp[1] = 30005; ans = 1;        int i,j;        for(i=1;i<=n;i++)        {            scanf("%d",&x);            for(j=1;j<=ans;j++)            {                if(x <= dp[j])                {                    dp[j] = x;                    break;                }            }            if(j > ans) dp[++ans] = x;        }        printf("%d\n",ans);    }    return 0;}

我们还可以进行优化。对于知道求最长递增子序列的O(nlogn)算法的人,其实接下来的思想和那个一样。
由于我们可以知道dp[i] 一定是一个单调递增序列,所以在第二维时我们是求出第一个比当前导弹高度大的第一个系统,所以我们可以进行二分查找。
我们可以直接使用lower_bound()函数

**
关于 lower_bound 和 upper_bound:
lower_bound 返回的是 >= 查找的数的第一个下标
upper_bound 返回的只是 > 查找的数的第一个下标

都是在数组中左闭右开区间中查找。
越界情况:如果查找的数 > 数组中所有的数,则返回数组尾部的下标,此时数组越界
**

时间复杂度:O(nlogn)
代码:

#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <algorithm>#include <cmath>using namespace std;const int maxn = 1000000;int dp[maxn];int ans,n,x;int main(){    while(scanf("%d",&n)!=EOF)    {        dp[0] = -1; ans = 0;        for(int i=1;i<=n;i++)        {            scanf("%d",&x);            int j = lower_bound(dp,dp+ans+1,x) - dp;            dp[j] = x;            if(j > ans) ans = j;        }        printf("%d\n",ans);    }    return 0;}
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 qq申请太多进不了热聊怎么办 手机号申请的微信号被盗了怎么办 买菜别人少找了钱不还怎么办 在掌上英雄联盟买皮肤买错区怎么办 win8我的电脑图标没了怎么办 英雄联盟老是卡在安全扫描怎么办 英雄联盟活动送皮肤没送怎么办 电脑换完系统有些页面打不开怎么办 王卡助手交手机费页面打不开怎么办 在浏览器上打不开路由器页面怎么办 英雄联盟读条的时候自动关机怎么办 手机的位置信息开不了怎么办呢 滴滴车主接到乘客返回路程要怎么办 移动换话费积分是发什么短信怎么办 手机店积分换手机被贷款怎么办 心悦俱乐部礼包已过期是怎么办 心悦兑换的东西不是账号绑定怎么办 心悦会员绑定的手机号不用了怎么办 想在京东商城开个网店怎么办呢 京东买了东西收货了不想要了怎么办 京东转卖的商品有问题怎么办 如果衣服下架了然后有退货怎么办 想买二手车可没有懂车的人怎么办 买车的时候异地车牌回家怎么办 天猫下单显示下单人数太多券怎么办 英雄联盟进入游戏后无限崩溃怎么办 打开电视显示百度影棒打不开怎么办 家里路由器网速一会快一会慢怎么办 用快看影视下载电影网速太慢怎么办 苹果手机下载东西网速特别慢怎么办 网上买重庆时时彩输了很多钱怎么办 找不到自己在哪个平台借过钱怎么办 九游账号绑定手机之前绑定的怎么办 九游充过钱的游戏忘了游戏名怎么办 百度网盘密码忘了申诉不了怎么办 手机号被别人注册了百度账号怎么办 快手被盗找回时出来重置密码怎么办 魅族账号密码和密保都忘记了怎么办 vivo账号的密保问题忘了怎么办 oppo账号密保问题忘了怎么办 小米手机刷了机忘了账号密码怎么办