当前位置:首页 > 提高组 > 1999年NOIP提高组导弹拦截(洛谷P1020)解题思路与动态规划代码解析

1999年NOIP提高组导弹拦截(洛谷P1020)解题思路与动态规划代码解析

4周前 (06-18)

1999年NOIP提高组导弹拦截(洛谷P1020)解题思路与动态规划代码解析  动态规划 最长上升子序列 最长下降子序列 NOIP提高组 第1张

一、题目解读

    1999年NOIP提高组“导弹拦截”问题(对应洛谷P1020)要求设计导弹拦截系统:给定一组导弹高度数据,需计算最少拦截系统数量,并求最多能拦截的导弹数。核心难点在于将问题转化为最长不上升子序列(第一问)与最长上升子序列(第二问)的求解,考验动态规划与序列分析能力。

二、解题思路

采用动态规划+二分查找优化策略:

    1. 第一问:最长不上升子序列(LDS)——维护一个存储当前最长LDS末尾元素的数组dp,通过upper_bound(从大到小查找第一个大于目标值的迭代器)动态更新,确保序列严格不上升。

    2. 第二问:最长上升子序列(LIS)——类似思路,利用lower_bound(从小到大查找第一个大于等于目标值的迭代器)维护LIS末尾,得到拦截系统数量。

    两者时间复杂度均为O(nlogn),避免暴力枚举

三、解题步骤

1. 数据输入:循环读入导弹高度,存入missiles向量。

2. LDS求解:遍历导弹高度,通过upper_bound在dp中查找可替换的末尾元素(若未找到则扩展序列),最终dp.size()即为拦截数。

3. LIS求解:同理用lower_bound更新tails数组,其大小即为所需系统数量。

4. 输出结果:两问答案分别对应LDS长度与LIS长度。

四、代码与注释

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr); // 加速IO

    vector<int> missiles; // 存储导弹高度
    int height;
    
    // 高效读取输入数据
    while (cin >> height) {
        missiles.push_back(height);
    }
    
    int n = missiles.size();
    
    // 第一问:O(nlogn)求最长不上升子序列
    vector<int> dp; // 存储LDS末尾元素
    for (int h : missiles) {
        auto it = upper_bound(dp.begin(), dp.end(), h, greater<int>()); // 从大到小查找第一个大于h的位置
        if (it == dp.end()) { // 若未找到,扩展序列
            dp.push_back(h);
        } else {
            *it = h; // 替换末尾元素(缩短序列长度)
        }
    }
    int max_intercept = dp.size(); // LDS长度即拦截数
    
    // 第二问:O(nlogn)求最长上升子序列
    vector<int> tails; // 存储LIS末尾元素
    for (int h : missiles) {
        auto it = lower_bound(tails.begin(), tails.end(), h); // 从小到大查找第一个大于等于h的位置
        if (it == tails.end()) {
            tails.push_back(h);
        } else {
            *it = h; // 替换末尾元素(优化序列长度)
        }
    }
    int system_count = tails.size(); // LIS长度即系统数量
    
    cout << max_intercept << "\n" << system_count << "\n";
    return 0;
}

五、总结

    本解法巧妙将导弹拦截问题转化为经典动态规划模型(LIS/LDS),并通过二分查找函数大幅优化效率。代码简洁且逻辑清晰,体现了“问题转化”与“算法优化”在竞赛编程中的重要性。掌握此类技巧,能有效应对涉及序列极值统计的复杂场景。



原创内容 转载请注明出处

分享给朋友:

相关文章

力扣5:中心扩散法 轻松破解最长回文子串

力扣5:中心扩散法 轻松破解最长回文子串

题目解读:在一个给定的字符串中,我们需要找到最长的回文子串。回文是指正读反读都相同的字符串,如"aba"、"abba"都是回文。这个问题看似简单,但要在字符串中...

NOIP2005 普及组 洛谷P1408 背包问题的空间优化技巧与实战应用

NOIP2005 普及组 洛谷P1408 背包问题的空间优化技巧与实战应用

题目重解想象你是一名药师,有t分钟在山上采集m种草药。每种草药需要time分钟采集,价值为num。这就像考试时分配时间做题,要选择收益最大的题目组合。题目要求计算在规定时间内能获得的最大草药价值。解题...

2024年GESP五级武器强化(洛谷B4071)解题代码C++版

2024年GESP五级武器强化(洛谷B4071)解题代码C++版

一、题目解读    2024年GESP(青少年软件编程能力等级考试)五级中的“武器强化”(洛谷平台题目编号B4071)是一道典型的算法优化问题。题目要求通过合理...

CSP-J方格取数题解|动态规划解法|洛谷P7074代码解析

CSP-J方格取数题解|动态规划解法|洛谷P7074代码解析

一、题目解读题目要求在一个n×m的网格中,从左上角到右下角选择一条路径,路径上的数字可重复取用,求取数之和的最大值。路径限制为仅能向右或向下移动。需注意路径的灵活性与重复取数的可能性,传统单向动态规划...

NOIP 2008火柴棒等式题解(C++代码实现)  动态规划与枚举算法详解

NOIP 2008火柴棒等式题解(C++代码实现) 动态规划与枚举算法详解

一、题目解读火柴棒等式问题(NOIP 2008,洛谷P1149)要求使用给定数量的火柴棒,构造形如 A + B = C 的等式,其中A、B、C均为整数,且火柴棒总数恰好等于输入值。需统计符合条件的等式...

洛谷P4551题解题报告:图论与Trie树优化异或路径问题的实战解析

洛谷P4551题解题报告:图论与Trie树优化异或路径问题的实战解析

一、题目解读洛谷P4551题要求在一个无向图中,寻找任意两点路径权值异或后的最大值。题目输入为图的边信息(点数n和n-1条边),每条边包含起点、终点及权值。需输出所有路径中权值异或的最大值。问题核心在...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。