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;
}


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

原文地址:https://www.cnblogs.com/DSChan/p/4862025.html