1260:【例9.4】拦截导弹(Noip1999)

题目来源:http://ybt.ssoier.cn:8088/problem_show.php?pid=1260

1260:【例9.4】拦截导弹(Noip1999)

时间限制: 1000 ms         内存限制: 65536 KB
提交数: 4533     通过数: 1660

【题目描述】

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

输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数,导弹数不超过1000),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

【输入】

输入导弹依次飞来的高度。

【输出】

第一行:最多能拦截的导弹数;

第二行:要拦截所有导弹最少要配备的系统数。

【输入样例】

389 207 155 300 299 170 158 65

【输出样例】

6
2

例题不怎么详的解:这是一道十分经典的LIS动规题目,难点和重点在于需要查找多条LIS并进行统计。这题说是dp,实则更像是纯模拟。我们抽丝剥茧,将本题数学框架讨论如下:首先我们要求的这个最多能拦截的导弹数,也就是给出序列的LIS,然后是拦截所有导弹最少要配备的系统数,也就是最少有几条公共子序列存在,注意,每条子序列必须是最优的。这个最优是什么意思呢?也就是每套系统(每条子序列)必须拦截下最多的导弹(拥有最长最优的长度)。

本题的算法,我借鉴的是书上的解法,这个解法是可以优化空间复杂度的,但是因为我是初学者,所以写出代码后也不大懂优化,只能勉勉强强按书上的来。第一问可以用dp解,第二问可以用贪心解。

算法分析:设置a[j]代表原序列中第j个元素,b[j]表示长度为j的LIS,h[k]表示第k个系统当前可拦截导弹的最高高度;
  1. 遍历已输入序列一次,maxx暂存当前导弹高度可用最长LIS的长度值,于是当前输入的导弹会使LIS长度maxx+1,并将此值存入b数组;
  2. 记录最长LIS的长度;
  3. 贪心计算本次导弹由哪一套系统拦截,若当前所有LIS均对当前输入导弹高度不可用,则新增一套系统拦截。
如果没看懂也无妨,后面会详细解释。

重头戏来了。

先初始化。

 dp部分很简单的:

1 maxx=0;
2 for(j=1;j<=i-1;j++)
3  if(a[j]>=a[i]&&b[j]>maxx) maxx=b[j];
4 b[i]=maxx+1;
5 if(b[i]>m) m=b[i];

 大概就是每输入一个数,遍历一遍当前序列,找一遍当前可构成的不下降序列。

 当然如果仅仅是这样就只能求出LIS,求不出最少的系统数,于是我们需要一个贪心:

 1 x=0;//当前使用的系统
 2 for(k=1;k<=n;k++)
 3     {
 4         if(h[k]>=a[i])//首先你这个系统你得可用
 5          if(x==0) x=k;
 6          else if(h[k]<h[x]) x=k;//选择当前可拦截高度最低的可用系统拦截
 7     }
 8     if(x==0){
 9         n++;x=n;
10     }
11     h[x]=a[i];

 完美。

 样例代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstdlib>
#include<queue>
#include<vector>
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define N 10010
#define MOD 2520
#define E 1e-12
/*This is an example*/
int i,j,k,x,n,maxx,m,a[N],b[N],h[N];

using namespace std;
int main()
{
    i=1;n=0;m=0;
    memset(a,0,sizeof(a));
    memset(b,0,sizeof(b));
    memset(h,0,sizeof(h));
    while(cin>>a[i])
    {
        maxx=0;
        for(j=1;j<=i-1;j++)
         if(a[j]>=a[i]&&b[j]>maxx) maxx=b[j];
        b[i]=maxx+1;
        if(b[i]>m) m=b[i];
        x=0;
        for(k=1;k<=n;k++)
        {
            if(h[k]>=a[i])
             if(x==0) x=k;
             else if(h[k]<h[x]) x=k;
        }
        if(x==0){
            n++;x=n;
        }
        h[x]=a[i];
        i++;
    }
    cout<<m<<endl<<n<<endl;
    return 0;
}

2019-05-03 12:34:13

原文地址:https://www.cnblogs.com/DarkValkyrie/p/10804810.html

时间: 2024-11-08 08:46:01

1260:【例9.4】拦截导弹(Noip1999)的相关文章

NOIP1999 拦截导弹

@font-face{ font-family:"Times New Roman"; } @font-face{ font-family:"宋体"; } @font-face{ font-family:"Symbol"; } @font-face{ font-family:"Wingdings"; } @font-face{ font-family:"黑体"; } @list l0:level1{ mso-

拦截导弹问题(Noip1999)

1322:[例6.4]拦截导弹问题(Noip1999) 时间限制: 1000 ms         内存限制: 65536 KB提交数: 3843     通过数: 1373 [题目描述] 某国为了防御敌国的导弹袭击,开发出一种导弹拦截系统,但是这种拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天,雷达捕捉到敌国的导弹来袭,由于该系统还在试用阶段.所以一套系统有可能不能拦截所有的导弹. 输入导弹依次飞来的高度(雷达给出的高度不大于30000

拦截导弹问题(NOIP1999)

某国为了防御敌国的导弹袭击,开发出一种导弹拦截系统,但是这种拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度, 但是以后每一发炮弹都不能高于前一发的高度.某天,雷达捕捉到敌国的导弹来袭,由于该系统还在试用阶段.所以一套系统有可能不能拦截所有的导弹. 输入导弹依次飞来的高度(雷达给出的高度不大于30000的正整数).计算要拦截所有导弹最小需要配备多少套这种导弹拦截系统.[输入格式] n颗依次飞来的高度(1≤n≤1000).[输出格式] 要拦截所有导弹最小配备的系统数k.[输入样例]miss

tyvj P1209 - 拦截导弹 平面图最小割&amp;&amp;模型转化

P1209 - 拦截导弹 From admin    Normal (OI)总时限:6s    内存限制:128MB    代码长度限制:64KB 背景 Background 实中编程者联盟为了培养技术精湛的后备人才,必须从基础题开始训练. 描述 Description 某国为了防御敌国的导弹袭击,研发出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天,雷达捕捉到敌国的导弹来袭.由于该系统还在试验阶段,所以只有

拦截导弹(线性动态规划)

1315: 拦截导弹 时间限制: 1 Sec  内存限制: 128 MB提交: 46  解决: 16[提交][状态][讨论版] 题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天,雷达捕捉到敌国的导弹来袭.由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹. 输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000 的正整数),计算这套系统最多能

nyoj 814 又见拦截导弹

又见拦截导弹 时间限制:3000 ms  |  内存限制:65535 KB 难度:3 描述 大家对拦截导弹那个题目应该比较熟悉了,我再叙述一下题意:某国为了防御敌国的导弹袭击,新研制出来一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能超过前一发的高度.突然有一天,雷达捕捉到敌国的导弹来袭.由于该系统存在缺陷,所以如果想把所有的导弹都拦截下来,就要多准备几套这样的导弹拦截系统.但是由于该系统成本太高,所以为了降低成本,请你计算一下最少需要

codevs 1044 拦截导弹 1999年NOIP全国联赛提高组

1044 拦截导弹 1999年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天,雷达捕捉到敌国的导弹来袭.由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹. 输入描述 Input Description 输入导弹

codevs1409 拦截导弹2

[问题描述]一场战争正在 A 国与 B 国之间如火如荼的展开.B 国凭借其强大的经济实力开发出了无数的远程攻击导弹,B 国的领导人希望,通过这些导弹直接毁灭 A 国的指挥部,从而取得战斗的胜利!当然,A 国人民不会允许这样的事情发生,所以这个世界上还存在拦截导弹.现在,你是一名 A 国负责导弹拦截的高级助理.B 国的导弹有效的形成了三维立体打击,我们可以将这些导弹的位置抽象三维中间的点(大小忽略),为了简单起见,我们只考虑一个瞬时的状态,即他们静止的状态.拦截导弹设计非常精良,可以精准的引爆对方

拦截导弹(南阳oj)(dp最长下降子序列)

拦截导弹 时间限制:3000 ms  |  内存限制:65535 KB 难度:3 描述 某国为了防御敌国的导弹袭击,发展中一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于等于前一发的高度.某天,雷达捕捉到敌国导弹来袭.由于该系统还在试用阶段,所以只用一套系统,因此有可能不能拦截所有的导弹. 输入 第一行输入测试数据组数N(1<=N<=10) 接下来一行输入这组测试数据共有多少个导弹m(1<=m<=20) 接下来行输