问题描述
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
输入格式
一行,为导弹依次飞来的高度
输出格式
两行,分别是最多能拦截的导弹数与要拦截所有导弹最少要配备的系统数
样例输入
389 207 155 300 299 170 158 65
样例输出
6
2
思路
- 读入导弹依次飞来的高度,并保存在数组a[]中,同时记录导弹数量size。
- 使用两个动态规划数组dpup[]和dpdown[]来记录递增和递减序列的长度。
- 遍历导弹高度数组a[],对每个导弹进行动态规划计算:
- 对每个导弹,向前遍历之前的导弹,更新递增和递减序列的长度。
- 记录当前最长的递减序列长度sum和递增序列长度num。
- 输出最多能拦截的导弹数sum和最少需要多少套拦截系统num。
首先,我们定义了几个全局变量,包括两个用于存储动态规划状态的数组dpup
和dpdown
,一个用于存储输入序列的数组a
,以及几个用于存储结果和临时变量的整数。
max
函数是一个简单的辅助函数,用于返回两个整数中的较大者。
在main
函数中,我们首先通过一个无限循环从标准输入读取整数序列,直到遇到换行符为止。然后,我们使用两个嵌套的循环来计算每个位置的最长上升子序列和最长下降子序列的长度。对于每个位置i
,我们检查所有在i
之前的位置j
,如果a[j]
大于或等于a[i]
,那么我们就更新dpdown[i]
为dpdown[j]+1
和dpdown[i]
中的较大者;否则,我们更新dpup[i]
为dpup[j]+1
和dpup[i]
中的较大者。这样,当我们遍历完所有的位置后,dpup[i]
和dpdown[i]
就分别存储了以a[i]
结尾的最长上升子序列和最长下降子序列的长度。
最后,我们遍历dpup
和dpdown
数组,找出其中的最大值,分别存储在sum
和num
中,这就是我们要找的最长的上升子序列和最长的下降子序列的长度。我们将这两个结果打印出来,然后程序结束。
代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
// dpup 和 dpdown 是动态规划数组,用于存储中间结果
// a 是用于存储输入的数组
// size 是输入的数量
// sum 和 num 是用于存储最长上升子序列和最长下降子序列的长度
int dpup[100];
int dpdown[100];
int a[100];
int size = 0;
int sum = 0;
int num = 0;
// max 函数返回两个数中的最大值
int max(int a, int b)
{
return a > b ? a : b;
}
// 主函数
int main()
{
// b, c, i, j, k 是未使用的变量
int b = 0, c = 0, i = 0, j = 0, k = 0;
// 无限循环,直到输入结束
for (i = 0;; i++)
{
// 读取一个整数并存储在 a[i] 中
// 增加 size 的值
// 如果读取到换行符,就跳出循环
scanf("%d", &a[i]);
size++;
if (getchar() == '\n')
{
break;
}
}
// 对于每个位置 i
for (i = 0; i < size; i++)
{
// 初始化 dpup[i] 和 dpdown[i] 为 1
dpup[i] = 1;
dpdown[i] = 1;
// 对于每个在 i 之前的位置 j
for (j = 0; j < i; j++)
{
// 如果 a[j] 大于或等于 a[i]
if (a[j] >= a[i])
{
// 更新 dpdown[i] 为 dpdown[i] 和 dpdown[j]+1 中的最大值
dpdown[i] = max(dpdown[i], dpdown[j] + 1);
}
// 否则
else
{
// 更新 dpup[i] 为 dpup[i] 和 dpup[j]+1 中的最大值
dpup[i] = max(dpup[i], dpup[j] + 1);
}
}
// 更新 sum 为 sum 和 dpdown[i] 中的最大值
sum = max(sum, dpdown[i]);
// 更新 num 为 num 和 dpup[i] 中的最大值
num = max(num, dpup[i]);
}
// 打印 sum 和 num
printf("%d\n%d", sum, num);
return 0;
}