-
题目描述:
-
某国为了防御敌国的导弹袭击,开发出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭,并观测到导弹依次飞来的高度,请计算这套系统最多能拦截多少导弹。拦截来袭导弹时,必须按来袭导弹袭击的时间顺序,不允许先拦截后面的导弹,再拦截前面的导弹。
-
输入:
-
每组输入有两行,第一行,输入雷达捕捉到的敌国导弹的数量k(k<=25),
第二行,输入k个正整数,表示k枚导弹的高度,按来袭导弹的袭击时间顺序给出,以空格分隔。
-
输出:
-
每组输出只有一行,包含一个整数,表示最多能拦截多少枚导弹。
-
样例输入:
-
8 300 207 155 300 299 170 158 65
-
样例输出:
-
6
-
第二次遇到类似的题目了,郁闷的是第一次做的时候AC了,这一次竟然想不起怎么做了,这脑袋。。。
-
题目分析典型的最长非递增子序列,首先想到动态规划算法;
-
构造递推关系,用b[i]来表示第i+1个数字,F[i]表示必须包含第i+1个数字的最大子序列长度;
-
递推关系如下:
-
F[0] = 1;F[i] = max{F[j]+1,F[i]},其中,0=<j<=i-1,并且b[j]>=b[i]
-
这样分析后,代码便可得出:
-
#include <stdio.h> int main(){ int b[25]; int f[25]; int n; int max; while(scanf("%d",&n) != EOF){ max = 0; for(int i = 0; i < n; i++){ f[i] = 1; } for(int i = 0; i < n; i++){ scanf("%d",&b[i]); } for(int i = 1; i < n; i++){ for(int j = 0; j < i; j++){ if(b[j] >= b[i]){ if(f[j] + 1 > f[i]){ f[i] = f[j] + 1; } } } } for(int i = 0; i < n; i++){ if(f[i] > max){ max = f[i]; } } printf("%d\n",max); } return 0; }