1 条题解

  • 0
    @ 2025-11-10 17:10:27

    好的,我来分析一下这段代码,然后给出题解和算法标签。


    代码分析

    1. 问题理解

    • nn 棵树排成一行,每棵树有高度 did_i
    • 小鸟从第 1 棵树飞到第 nn 棵树
    • 每次可以飞 11kk 棵树的距离
    • 从较低或等高的树飞到更高或等高的树会疲惫(计数+1)
    • 目标:最小化疲惫次数

    2. 算法核心 - 单调队列优化 DP

    状态定义

    f[i] 表示飞到第 ii 棵树的最小疲惫次数。

    状态转移

    f[i] = f[dq[hd]] + (d[i] >= d[dq[hd]]);
    

    从队列头部的最优决策树 dq[hd] 飞到第 ii 棵树:

    • 如果 d[i]d[dq[hd]]d[i] \geq d[dq[hd]],疲惫次数+1
    • 否则,疲惫次数不变

    单调队列维护

    // 维护队列范围
    if (i - dq[hd] > k) hd++;
    
    // 插入新元素
    if (d[i] < d[dq[hd]]) {
        while (hd <= tl && d[dq[tl]] <= d[i]) tl--;
        dq[++tl] = i;
    }
    

    队列保持:

    1. 范围有效性:队首元素在 kk 步范围内
    2. 单调性:队尾到队首,树高递减(保证队首是最优决策)

    算法标签

    基于代码分析,主要算法标签包括:

    • 动态规划 (Dynamic Programming)
    • 单调队列优化 (Monotonic Queue Optimization)
    • 滑动窗口最值 (Sliding Window Maximum/Minimum)
    • 最优化问题 (Optimization Problem)

    题解

    「XXI Olimpiada Informatyczna」小鸟 题解

    题目分析

    小鸟需要从第 1 棵树飞到第 nn 棵树,每次最多飞 kk 棵树的距离。从较低树飞到较高或等高的树会感到疲惫,目标是最小化疲惫次数。

    关键观察

    1. 最优子结构:到达第 ii 棵树的最小疲惫次数,可以由前面 kk 棵树中的某棵转移而来
    2. 决策单调性:如果从树 jj 飞到树 ii 不会增加疲惫(d[i]<d[j]d[i] < d[j]),那么树 jj 是比后面更高树更好的决策点
    3. 滑动窗口:对于每个位置 ii,只需要考虑前 kk 棵树作为可能的起点

    算法思路

    动态规划 + 单调队列优化

    状态定义

    f[i] 表示飞到第 ii 棵树的最小疲惫次数。

    状态转移

    对于每个位置 ii

    f[i] = min{ f[j] + (d[i] >= d[j]) },其中 i-k ≤ j < i
    

    单调队列优化

    使用双端队列维护可能的最优决策:

    1. 队列性质

      • 按树高递减排列
      • 所有元素在当前位置的 kk 步范围内
    2. 队列操作

      • 出队首:当队首元素超出 kk 步范围时
      • 出队尾:当新树比队尾树矮时,队尾不可能成为未来最优决策
      • 入队:新树如果比队首树矮,加入队列
    3. 决策选择

      • 总是选择队首作为当前最优决策
      • 如果飞到更高树,疲惫计数+1

    算法步骤

    int solve(int k) {
        初始化队列,加入第1棵树
        for i = 2 to N:
            // 维护队列范围
            if (i - 队首 > k) 队首出队
            
            // 计算f[i]
            f[i] = f[队首] + (d[i] >= d[队首])
            
            // 维护队列单调性
            if (d[i] < d[队首]) {
                while (队尾树高 ≤ d[i]) 队尾出队
                将i加入队尾
            }
        return f[N]
    }
    

    复杂度分析

    • 时间复杂度O(n)O(n) 每个元素最多入队出队一次
    • 空间复杂度O(n)O(n) 存储队列和DP数组
    • 查询处理O(qn)O(q \cdot n),但由于 q25q \leq 25,总复杂度可接受

    算法正确性

    该算法正确性的保证:

    1. 最优性:队列始终保持当前最优决策
    2. 单调性:队列按树高递减,确保矮树优先
    3. 完整性:考虑所有可能的转移

    样例验证

    样例输入

    9
    4 6 3 6 3 7 2 6 5
    2
    2
    5
    

    输出:21

    分析:

    • k=2k=2 时,路径 1→3→5→7→8→9,疲惫2次
    • k=5k=5 时,路径 1→6→9,疲惫1次

    总结

    本题通过单调队列优化动态规划,高效解决了带约束的最短路径问题。算法利用决策单调性将复杂度从 O(nk)O(nk) 优化到 O(n)O(n),能够处理大规模数据。

    最终算法标签动态规划 单调队列 滑动窗口 最优化

    • 1

    信息

    ID
    5149
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    2
    已通过
    1
    上传者