洛谷 P1020 导弹拦截 题解

时间:2021-09-08 18:43:56

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置。

题目链接:https://www.luogu.org/problem/show?pid=1020

题目描述

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

输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

输入输出格式

输入格式:

一行,若干个正整数最多100个。

输出格式:

2行,每行一个整数,第一个数字表示这套系统最多能拦截多少导弹,第二个数字表示如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

输入输出样例

输入样例#1:
389 207 155 300 299 170 158 65
输出样例#1:
6
2


分析:
求方案数一直是我很头疼的一个东西……
这个题分了两部分来求,第一部分DP求最大拦截数,第二部分贪心求拦截装置数量。
(结果代码变得很长很丑)
洛谷上有人说贪心AC的原因是数据太弱,应该用DP做第二部分。
并不是说贪心是错误的,还是要看你怎么贪www
判断导弹高度的时候≥是关键。

丑陋的AC代码:
 1 #include <iostream>
2 #include <cstdio>
3 #include <cstring>
4 #include<algorithm>
5
6 using namespace std;
7 int f[105],a[105];
8 int high[110];
9 int main()
10 {
11 int n = 0,x;
12 while(scanf("%d",&x) != EOF)
13 a[++ n] = x ;
14 for(int i = 1;i <= n;i ++)
15 {
16 for(int j = 1;j < i;j ++)
17 {
18 if (a[j]>=a[i])
19 f[i] = max(f[i],f[j]);
20 }
21 f[i]++;
22 }
23 int ans = 0;
24 for(int i = 2;i <= n;i ++)
25 ans = max(ans,f[i]);
26 printf("%d\n",ans);
27 int tot = 1,tmp = 0;
28 memset(high,0x3f,sizeof(high));
29 for(int i = 1;i <= n;i ++)
30 {
31 for(int j = 0;j < tot;j ++)
32 {
33 if(high[j] >= a[i])
34 {
35 high[j] = a[i];
36 break;
37 }
38 else if(j == tot - 1)
39 tot ++;
40 }
41 }
42 printf("%d\n",tot);
43 return 0;
44 }