noip提高组1999 导弹拦截

来源:互联网 发布:mac的ps怎么安装 编辑:程序博客网 时间:2024/06/05 13:21

导弹拦截

背景

实中编程者联盟为了培养技术精湛的后备人才,必须从基础题开始训练。

描述

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

格式

输入格式

输入数据只有一行,该行包含若干个数据,之间用半角逗号隔开,表示导弹依次飞来的高度(导弹最多有 20 枚,其高度为不大于 30000 的正整数)。

输出格式

输出数据只有一行,该行包含两个数据,之间用半角逗号隔开。第一个数据表示这套系统最多能拦截的导弹数;第二个数据表示如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

样例1

样例输入1

389 207 155 300 299 170 158 65

样例输出1

6 2

限制

每个测试点限时 1 秒。

 

这题是一题dp题。

第一问就是求LIS(最长不下降子序列),设dp[i]为以i结尾的序列的LIS,则有状态转移方程:dp[i]=max{dp[j]+1} (j<i  a[j]<a[i])

而第二问可以dp(不会),可以贪心,我用的是贪心,先是只有一个系统,扫一遍,如果这个导弹可以加入某个系统,就加进去,否则新开一个系统。

#include <algorithm>#include <cstdio>using namespace std;int f[101],dp[101],last[101];int main() {    int x,ans = 0;    while (scanf("%d",&x) != EOF) f[++f[0]] = x;    for (int i = 0;i <= f[0];i++)        for (int j = 0;j < i;j++)            if (f[j] >= f[i]) dp[i] = max(dp[i],dp[j]+1);    for (int i = 1;i <= f[0];i++) dp[0] = max(dp[0],dp[i]);    printf("%d\n",dp[0]+1);    for (int i = 1;i <= f[0];i++) {        bool flag = false;        for (int j = 1;j <= ans;j++)            if (last[j] >= f[i]) {                last[j] = f[i];                flag = true;                break;            }        if (!flag) {            ans++;            last[ans] = f[i];        }    }    printf("%d",ans);    return 0;}