描述
某国为了防御敌国的导弹袭击,发展中一种导弹拦截系统。但是这种导弹拦截系统 有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国导弹来袭。由于该系统还在试用阶段 ,所以只用一套系统,因此有可能不能拦截所有的导弹。
输入
第一行输入测试数据组数N(1<=N<=10)
接下来一行输入这组测试数据共有多少个导弹m(1<=m<=20)
接下来行输入导弹依次飞来的高度,所有高度值均是大于100的正整数。
输出
输出最多能拦截的导弹数目
样例输入
2
8
389 207 155 300 299 170 158 65
3
88 34 65
样例输出
6
2
解题思路:
动态规划------最长单调递减序列
需要2个数组,第一个用于记录原始导弹的信息。
第二个数组用于存放满足题意的最长单调递减序列 即能拦截的导弹的最大数量
1.第一个元素存入数组
2.第二个进入时与第一个比较,若小于第一个元素,存入数组的尾部。若大于第一个元素,则覆盖第一个元素(核心步骤:提高最长单调递减序列的上界,使更多的元素进入此序列)。
3.第三个元素,与第一个元素比较,若小于,与第二个元素比较,若小于,存入数组的尾部。若大于第一个或者第二个元素,则覆盖该元素。
4.重复以上步骤即可(递推思想)
注:
此方法无法输出拦截导弹的顺序,只能统计拦截导弹的最大个数。因为元素覆盖后,个数不变,但是拦截的导弹的顺序已经改变。若要求得拦截导弹的顺序,则需要另外一个与原始数据大小相同的数组,记录第i个导弹的前驱元素。
如上题:
c数组:
下标 0 1 2 3 4 5 6 7
前驱 0 1 2 1 4 5 6 7
对bomb数组
for(int i = x(即7); i != 0; i = c[i])
{
if(i == x) cout<<bomb[i]<<" ";
cout<<bomb[c[i]]<<" ";
}
然后翻转即为导弹拦截顺序
代码如下:
#include<iostream> using namespace std; int bomb[21]; int result[21]; int main() { int N; cin>>N; while(N--) { int n, i, j; cin>>n; for(i = 0; i < n; ++i) { cin>>bomb[i]; } result[0] = bomb[0]; int sum = 1; for(int i = 0; i < n; ++i) { for(j = sum - 1; j >= 0; --j) { if(result[j] > bomb[i]) break; } result[j + 1] = bomb[i]; if(j == sum - 1) { sum++; } } cout<<sum<<endl; } return 0; }