某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
输入导弹依次飞来的高度,计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
一行,若干个整数,中间由空格隔开。
两行,每行一个整数,第一个数字表示这套系统最多能拦截多少导弹,第二个数字表示如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
389 207 155 300 299 170 158 65
6
2
对于前 $50%$ 数据(NOIP 原题数据),满足导弹的个数不超过 $10^4$ 个。该部分数据总分共 $100$ 分。可使用$\mathcal O(n^2)$ 做法通过。
对于后 $50%$ 的数据,满足导弹的个数不超过 $10^5$ 个。该部分数据总分也为 $100$ 分。请使用 $\mathcal O(n\log n)$ 做法通过。
对于全部数据,满足导弹的高度为正整数,且不超过 $5\times 10^4$。
此外本题开启 spj,每点两问,按问给分。
$\text{upd 2022.8.24}$:新增加一组 Hack 数据。
洛谷P1020题目是一个经典的动态规划问题,可以使用贪心策略来解决。
思路如下:
创建一个空数组 missiles 来存储导弹的高度。
读入导弹的高度,并将其添加到 missiles 数组中。
创建一个空数组 dp 来存储每个位置上的最长不上升子序列的长度。
遍历 missiles 数组,对于每个导弹的高度,将其插入到 dp 数组中适当的位置,并更新 dp 数组。
如果导弹的高度大于等于 dp 数组的最后一个元素,将其添加到 dp 数组末尾。
否则,在 dp 数组中使用二分查找找到第一个大于等于该导弹高度的位置,并将该位置的元素替换为导弹高度。
最终 dp 数组的长度即为能够拦截的最多导弹数目。
为了拦截所有的导弹,最少需要配备的拦截系统数目等于导弹总数减去能够拦截的最多导弹数目。
下面是一个示例的Python代码实现:
python
Copy code
missiles = list(map(int, input().split()))
dp = []
for h in missiles:
if not dp or h >= dp[-1]:
dp.append(h)
else:
left, right = 0, len(dp) - 1
while left < right:
mid = (left + right) // 2
if dp[mid] >= h:
left = mid + 1
else:
right = mid
dp[left] = h
max_intercept = len(dp)
min_systems = len(missiles) - max_intercept
print(max_intercept)
print(min_systems)
希望这个解法能够帮助到您解决洛谷P1020题目。如果您有任何疑问,请随时向我提问。
示例代码:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
vector<int> heights; // 存储导弹高度的数组
int height;
while (cin >> height) {
heights.push_back(height);
}
int maxCount = 0; // 最多能拦截的导弹数量
int minSets = 0; // 最少需要配备的拦截系统数量
vector<int> dp; // 动态规划数组,用于记录当前高度的最长递减子序列长度
for (int i = 0; i < heights.size(); i++) {
height = heights[i];
auto it = lower_bound(dp.begin(), dp.end(), height); // 使用二分查找找到当前高度在dp数组中的位置
if (it == dp.end()) {
dp.push_back(height); // 当前高度比之前所有导弹的高度都大,所以将其插入dp数组中
minSets++; // 需要增加一个新的拦截系统
} else {
*it = height; // 更新dp数组中的值
}
maxCount = max(maxCount, int(dp.size())); // 更新最多能拦截的导弹数量
}
cout << maxCount << endl;
cout << minSets << endl;
return 0;
}
怎么结束帖啊?