• codevs1044 拦截导弹(最长不下降子序列dp)


    题目描述 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

    这题数据很小,当时我就用了求多次LIS的方法给过了,后来一搜才发现还有个很高端的定理。

    具体看这个 http://blog.csdn.net/acdreamers/article/details/7626671


    我水水的代码。

    求完一遍LIS后把当中的元素标记删除,接着再求。有多少个LIS就是要建多少个系统了。

    #include<iostream>
    #include<cassert>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<string>
    #include<iterator>
    #include<cstdlib>
    #include<vector>
    #include<stack>
    #include<map>
    #include<set>
    using namespace std;
    #define rep(i,f,t) for(int i = (f),_end_=(t); i <= _end_; ++i)
    #define rep2(i,f,t) for(int i = (f),_end_=(t); i < _end_; ++i)
    #define dep(i,f,t) for(int i = (f),_end_=(t); i >= _end_; --i)
    #define dep2(i,f,t) for(int i = (f),_end_=(t); i > _end_; --i)
    #define clr(c, x) memset(c, x, sizeof(c) )
    typedef long long int64;
    const int INF = 0x5f5f5f5f;
    const double eps = 1e-8;
    
    
    //*****************************************************
    int n;
    int a[30];
    int d[30],p[30];
    bool h[30];
    bool ok(){for(int i = 1; i < n; ++i) if(!h[i])return false; return true;}
    int solve()
    {
        for(int i = 1; i <= n; ++i)
        {
            d[i] = 1;
            if(h[i])continue;
            for(int j = i-1; j >= 0; --j)
            {
                if(h[j])continue;
                if(a[i] >= a[j] && d[j]+1 > d[i]){
                    d[i] = d[j] + 1;
                    p[i] = j;
                }
            }
        }
        return d[n] - 1;
    }
    void del(int i){
        if(!i)return;
        h[i] = 1;
        del(p[i]);
    }
    int main()
    {
    
        while(scanf("%d",&a[++n]) == 1);
        --n;
        reverse(a+1,a+n+1);                         //写代码的时候一顺手就打成了上升的,索性就这么干了
        a[++n] = 400000;                        //加这一个保证LIS的结尾元素总是在n号位置
        int ans1 = 0,ans2 = 0;
        while(!ok()){
            ++ans2;
            h[n] = 0;
            int tmp = solve();
            ans1 = max(ans1,tmp);
            del(n);
        }
        printf("%d
    %d
    ",ans1,ans2);
    
        return 0;
    }
    


    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    ccf-csp201909题解
    TYUT程序设计入门第四讲练习题题解--数论入门
    Pairs Forming LCM (LightOJ
    Help Hanzo (LightOJ
    hnsdfz -- 6.19 -- day4
    hsdfz -- 6.18 -- day3
    hsdfz -- 6.17 -- day2
    hsdfz -- 6.16 -- day1
    【BZOJ2555】SubString
    洋葱第4场C和D题解……
  • 原文地址:https://www.cnblogs.com/DSChan/p/4862025.html
Copyright © 2020-2023  润新知