Code[VS]1044拦截导弹

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

输入描述 Input Description
输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数)

输出描述 Output Description
输出这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

样例输入 Sample Input
389 207 155 300 299 170 158 65

样例输出 Sample Output
6
2

数据范围及提示 Data Size & Hint

导弹的高度<=30000,导弹个数<=20

这道题目来自1999年NOIP全国联赛提高组。是一个基础的序列型动态规划问题。看到题目就知道第一个问题是严格递减子序列问题。比较有趣的是第二个问题,最少需要几套系统才能拦截所有导弹,就是有多少个递减序列。第一个想法就是把最长的递减子序列给排除之后对剩余的元素再来排除,最终得到最后结果。但是这个想法实现比较困难。

这里给出答案,即序列的最长单调递增序列长度为第二问的答案。

假如某序列完全递减,则最长递增子序列长度为1,即只有一个最长递减子序列。
假如某序列完全递增,则最长递增子序列长度为n,即有n个最长递减子序列。(n为该序列长度)
那么对于某序列有增有减,则该序列所形成的严格单调递增序列必然为其每个互相完全不相同单调递减序列的某一个元素共同构成,即对于序列100 68 66 56 78 89 66 20 9,其严格单调递增序列为56 78 89。显然56,78,89永远为三个不同的递减序列中的元素。

假如严格单调递增序列的元素不为不同的递减序列的元素。即某个递减序列贡献了多个元素为严格单调递增序列元素,那么显然这多个元素是单调递增的,与递减序列矛盾。即可证明。

#include <cstdio>
#include <iostream>
using namespace std;

int main()
{
    int i = 0, res = 0, ans = 0;
    int mis[21] = {0}, up[21] = {0}, down[21] = {0};
    while(cin>>mis[i])
    {
        int _max = 0,max_ = 0;
        up[i] = 1;
        down[i] = 1;
        for(int j = 0; j < i; j++)
        {
            if(mis[j] < mis[i] && up[j] > _max)
                _max = up[j];
            if(mis[j] > mis[i] && down[j] > max_)
                max_ = down[j];
        }
        up[i] = _max + 1;
        down[i] = max_ + 1;
        res = max(res,up[i]);
        ans = max(ans,down[i]);
        i++;
    }
    cout<<ans<<endl<<res;
    return 0;
}

如有哪里疏漏,希望能够帮忙指正。

posted @ 2015-07-24 20:04  _Wilbert  阅读(130)  评论(0编辑  收藏  举报