九度oj 题目1112:拦截导弹

题目描述:
某国为了防御敌国的导弹袭击,开发出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭,并观测到导弹依次飞来的高度,请计算这套系统最多能拦截多少导弹。拦截来袭导弹时,必须按来袭导弹袭击的时间顺序,不允许先拦截后面的导弹,再拦截前面的导弹。 
 
输入:
每组输入有两行,
第一行,输入雷达捕捉到的敌国导弹的数量k(k<=25),

第二行,输入k个正整数,表示k枚导弹的高度,按来袭导弹的袭击时间顺序给出,以空格分隔。

输出:
每组输出只有一行,包含一个整数,表示最多能拦截多少枚导弹。
 
样例输入:
8
300 207 155 300 299 170 158 65
样例输出:
6
 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <string>
 5 #define MAX 30
 6 using namespace std;
 7 
 8 int num[MAX];
 9 int count[MAX];
10 
11 int main(int argc, char const *argv[])
12 {
13     int n;
14     //freopen("input.txt","r",stdin);
15     
16     while(scanf("%d",&n) != EOF) {
17         if(n <= 0) {
18             printf("0
");
19             continue;
20         }
21         for(int i = 0; i < n; i++) {
22             scanf("%d",&num[i]);
23             count[i] = 1;
24         }
25         count[n - 1] = 1;
26         int max = 1;
27         for(int j = n - 2; j >= 0; j--) {
28             int maxMin = -1;
29             for(int k = j + 1; k < n; k++) {
30                 if(num[k] <= num[j] && maxMin == -1) {
31                      maxMin = k;
32                 }
33                 else if(num[k] <= num[j] && count[k] > count[maxMin]) {
34                        maxMin = k;
35                 }
36             }
37             if(maxMin != -1) {
38                 count[j] = count[maxMin] + 1;
39             }
40             if(max < count[j]) {
41                 max = count[j];
42             }
43         }
44         printf("%d
",max);
45         /*for(int i = 0; i < n; i++) {
46             printf("%d ",count[i]);
47         }
48         printf("
");*/
49     }
50 
51     return 0;
52 }

做这道题是脑子犯了糊涂,在33行应比较count而不是比较num,导致错误了3次,此处count[k]取大于或大于等于count[maxMin]均可。

另外需注意n == 0时的情况

----------2016-9-17更新

现在再看这到题,它要我们求的其实是一个不严格下降子序列(即非上升子序列)的最长长度。

----------2016-11-23更新

今天在nyoj上发现一道一模一样的题(题目79),题目如下

拦截导弹

时间限制:3000 ms  |  内存限制:65535 KB
难度:3
 
描述

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

 
输入
第一行输入测试数据组数N(1<=N<=10)
接下来一行输入这组测试数据共有多少个导弹m(1<=m<=20)
接下来行输入导弹依次飞来的高度,所有高度值均是大于0的正整数。
输出
输出最多能拦截的导弹数目
样例输入
2
8
389 207 155 300 299 170 158 65
3
88 34 65
样例输出
6
2

代码如下
 1 #include <cstdio>
 2 #include <cstring>
 3 
 4 int s[100005];
 5 int dp[22];
 6 
 7 int main(int argc, char const *argv[])
 8 {
 9     int n;
10     scanf("%d",&n);
11     while(n--) {
12         int m;
13         scanf("%d",&m);
14         for(int i = 0; i < m; i++) {
15             scanf("%d",&s[i]);
16         }
17         memset(dp, 0, sizeof(dp));
18 
19         dp[0] = 1;
20         int ans = 1;
21         for(int i = 1; i < m; i++) {
22             int maxv = 0;
23             for(int j = i-1; j >= 0; j--) {
24                 if(s[j] > s[i] && maxv < dp[j]) {
25                     maxv = dp[j];
26                 }
27             }
28             dp[i] = maxv+1;
29             if(ans < dp[i]) {
30                 ans = dp[i];
31             }
32         }
33         printf("%d
", ans);
34     }
35     return 0;
36 }
原文地址:https://www.cnblogs.com/jasonJie/p/5684269.html