最少拦截系统-动态规划LIS

问题来源:hdu-1257

最少拦截系统

Problem Description

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

 

Input

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

 

Output

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

Sample Input

8

389 207 155 300 299 170 158 65

Sample Output

2

源代码:

#include<stdio.h>
#include<string.h>
#define MAX 100000
#define INF (1<<30)

int N , missle[MAX] , dp[MAX] , min[MAX];
//missle[i]存储第i-1个导弹的高度
//dp[i]表示第i-1个导弹以前拦截的系统最小数
//min[i]表示拦截系统数i的情况下最小高度

int main( ){
    int i , j , max;
    while( ~scanf("%d",&N) ){
        for( i=0 ; i<N ; i++ )
            scanf("%d",&missle[i]);

        max = 1;    //最小系统数是1
        memset( dp , 0 , sizeof( dp ) );

        dp[0] = 1;    //第一个导弹拦截的数目是1
        min[1] = missle[0];    //第一个系统的最小拦截高度是第一个导弹的高度missle[0]

        for( i=1 ; i<N ; i++ ){    //对于每一个导弹
            for( j=0 ; j<i ; j++ )    //之前的每一个导弹
                if( missle[i]<=missle[j] && missle[i]<min[dp[j]] ){
                    //如果i导弹比j导弹高度低 && i导弹比j导弹所在系统的最低高度还低
                    min[dp[j]] = missle[i];    //该系统的最低高度更新为此时的导弹高度
                    dp[i] = max;    //dp[i]为之前导弹的最小值
                    break;
                }
            if( !dp[i] ){    //若dp值没被更新
                dp[i] = ++max;    //新增加系统
                min[dp[i]] = missle[i];    //新增加的系统高度为当前导弹高度
            }
        }

        printf("%d\n",dp[N-1]);    //最小系统数
    }

    return 0;
}

代码分析:如果采用LIS(最长上升子序列,这题是最长下降子序列,思路一样)的算法,时间复杂度很高,所以进行改进,dp[i]改为i之前导弹的最小系统数,min[i]为第i个系统的最小高度,这样能减少时间的消耗.可能会有人问:当很多系统都可以容纳当前待加入的导弹时,为什么不更新导弹高度最小的那个系统,这样的话才可能使得其他系统高度尽可能被拉低地最小.我之前也在想这个问题(AC了,不过感觉还是有bug),后来用100 20 100 10 8 20这组数据才明白,我这样的算法使得min[]这个数组的数值是非递减的.所以找到每一个满足要求的系统,一定是最优的. 很多说不清楚的地方还请原谅我的知识库,嘿嘿..

    原文作者:动态规划
    原文地址: https://blog.csdn.net/u014366015/article/details/23781021
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞