当前位置:首页 > 蓝桥杯 > 洛谷P10909题(2024蓝桥杯国B):二分查找+贪心算法解决立定跳远

洛谷P10909题(2024蓝桥杯国B):二分查找+贪心算法解决立定跳远

1个月前 (08-15)

洛谷P10909题(2024蓝桥杯国B):二分查找+贪心算法解决立定跳远 洛谷题解 二分查找 贪心算法 蓝桥杯 国赛 第1张

一、题目解读

洛谷P10909是一道典型的贪心策略问题,要求在一个递增数列中,通过跳跃到达终点,并允许使用一次“爆发技能”以扩大单次跳跃距离。题目核心在于如何在限定跳跃次数内,合理分配普通跳跃与技能使用,找到最优的最大跳跃距离。

二、解题思路

1. 核心思想:采用二分查找确定最大可行跳跃距离。由于跳跃次数与距离呈反比关系,可通过二分法缩小解的范围。

2. 贪心优化:引入“爆发技能”的两种使用场景——中途遇长距离时使用,或末尾补用(若未使用过)。通过检查函数判断当前距离是否满足条件,并优先利用技能减少总次数。

三、解题步骤

1. 输入处理:读取n(元素数量)、m(最大跳跃次数)及数列a。

2. 特殊情况:n=1时直接输出(a[0]+1)/2,避免二分退化。

3. 二分查找区间:left=1,right=末尾元素值,通过mid=(left+right)/2迭代

4. 检查函数逻辑:

○ 遍历数列,计算相邻距离dist。

○ 若use_boost且未使用技能,且dist>mid但≤2*mid,则触发技能并更新位置。

○ 若dist>mid,按普通规则累加跳跃次数(cnt)。

○ 末尾检查:若技能未用且末尾距离符合条件,补用技能。

5. 二分终止条件:找到满足check(mid, m, false)或check(mid, m, true)的最大mid值。

四、代码与注释

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

bool check(long long L, const vector<int>& a, int m, bool use_boost) {
    int cnt = 0;
    long long prev = 0;
    bool boost_used = false;
    
    for (int i = 0; i < a.size(); ++i) {
        long long dist = a[i] - prev;
        if (use_boost && !boost_used && dist > L) {
            // 尝试在此处使用爆发技能
            if (dist <= 2 * L) {
                boost_used = true;
                prev = a[i];
                continue;
            }
        }
        
        if (dist > L) {
            cnt += (dist - 1) / L;
            if (cnt > m) return false;
        }
        prev = a[i];
    }
    
    // 如果使用爆发技能但没用上,尝试在最后使用
    if (use_boost && !boost_used) {
        long long last_dist = a.back() - (a.size() > 1 ? a[a.size()-2] : 0);
        if (last_dist > L && last_dist <= 2 * L) {
            boost_used = true;
        }
    }
    
    return cnt <= m && (!use_boost || boost_used);
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int n, m;
    cin >> n >> m;
    vector<int> a(n);
    for (int i = 0; i < n; ++i) {
        cin >> a[i];
    }
    
    // 处理特殊情况:n=1时只需要跳一次
    if (n == 1) {
        cout << (a[0] + 1) / 2 << endl;
        return 0;
    }
    
    long long left = 1, right = a.back(), ans = a.back();
    while (left <= right) {
        long long mid = (left + right) / 2;
        if (check(mid, a, m, false) || check(mid, a, m, true)) {
            ans = mid;
            right = mid - 1;
        } else {
            left = mid + 1;
        }
    }
    
    cout << ans << endl;
    return 0;
}

五、总结

本解法通过二分查找高效定位最优跳跃距离,结合贪心策略灵活处理爆发技能的使用时机,兼顾了时间与空间效率。关键在于将跳跃次数转化为距离约束,并利用技能的双条件检查实现全局优化。该思路适用于类似需要动态平衡资源分配的问题。


原创内容 转载请注明出处

分享给朋友:

相关文章

2022年蓝桥杯省赛B组扫雷(洛谷P8785)解题全解析:代码+思路+步骤详解

2022年蓝桥杯省赛B组扫雷(洛谷P8785)解题全解析:代码+思路+步骤详解

一、题目解读2022年蓝桥杯省赛B组机器人塔(洛谷P8785)是一道经典的算法题目,要求处理在一个二维平面上布置的炸雷与排雷火箭。炸雷具有爆炸半径,当排雷火箭引爆后,会触发周围范围内未被引爆的炸雷,形...

GESP五级题巧夺大奖解题报告:贪心算法优化与代码实现(洛谷B3872)

GESP五级题巧夺大奖解题报告:贪心算法优化与代码实现(洛谷B3872)

一、题目解读2023年GESP五级题目“巧夺大奖”(洛谷B3872)是一个经典的资源分配问题。题目要求玩家在有限时间内选择多个游戏,每个游戏有截止时间和奖励值,需在截止时间前完成游戏以获得奖励。目标是...

牛客23458题解析:基于二分查找的动态规划解法与代码实现

牛客23458题解析:基于二分查找的动态规划解法与代码实现

一、题目解读牛客23458题要求将给定的整数数组划分为m个连续子数组,使得每个子数组的和不超过某个最大值,且该最大值尽可能小。题目本质是求解“最小化最大值”的优化问题,需要结合二分查找与动态规划思想,...

洛谷1656题解:基于Tarjan算法求解割边问题(附代码与详细步骤)

洛谷1656题解:基于Tarjan算法求解割边问题(附代码与详细步骤)

一、题目解读洛谷1656题要求在无向图中找出所有割边(即删除后导致图不连通的边)。题目核心在于判断图的连通性,并识别哪些边是“桥”。需理解图论中的连通分量概念,以及如何通过算法高效定位割边。二、解题思...

洛谷2652题解析:同花顺排序问题的动态规划与滑动窗口优化

洛谷2652题解析:同花顺排序问题的动态规划与滑动窗口优化

一、题目解读洛谷2652题要求对一组扑克牌进行排序,目标是找到最少需要调整的次数,使得所有牌形成同花顺。题目中,扑克牌由花色和数字组成,需先按花色排序,再在同花色内按数字排序。核心难点在于如何处理花色...

洛谷P3694题解:动态规划与状态压缩优化解题全解析

洛谷P3694题解:动态规划与状态压缩优化解题全解析

一、题目解读洛谷P3694题要求解决一个多团队人数分配问题,给定n个元素和m个团队,每个元素属于一个团队,需将元素重新排列,使相邻元素属于不同团队,并最小化调整次数。题目难点在于如何高效处理团队间的空...

发表评论

访客

看不清,换一张

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