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

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

5个月前 (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;
}

五、总结

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


原创内容 转载请注明出处

分享给朋友:

相关文章

征服力扣704题:三步掌握经典二分查找算法

征服力扣704题:三步掌握经典二分查找算法

题目重解我们面对的是算法领域最经典的二分查找问题:在一个已排序的整数数组中,快速定位目标值的位置。就像在一本按字母顺序排列的字典中查找单词,我们不需要逐页翻阅,而是通过不断折半的方式快速缩小搜索范围,...

2012年NOIP提高组「借教室」题目(P1083)解题思路与二分查找优化代码解析

2012年NOIP提高组「借教室」题目(P1083)解题思路与二分查找优化代码解析

一、题目解读本题为2012年NOIP提高组中的「借教室」问题(洛谷P1083),要求处理教室借用订单的分配问题。给定n天每天可用教室数量r和m个订单(订单包含需求教室数d、开始日期s、结束日期t),判...

【牛客13256题解析】贪心算法优化题目组合问题:三元组与二元组的解题思路

【牛客13256题解析】贪心算法优化题目组合问题:三元组与二元组的解题思路

一、题目解读牛客13256题要求处理一组题目难度数据,通过组合三元组(难度差≤20)或二元组(难度差≤10)来重新编排题目,计算需要补充的最小题目数量。题目本质是资源分配与优化问题,需高效组合现有题目...

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

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

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

洛谷P2190题解:铁路售票系统车厢计算(差分数组+前缀和优化)

洛谷P2190题解:铁路售票系统车厢计算(差分数组+前缀和优化)

一、题目解读洛谷P2190题要求解决铁路售票系统中的车厢数量计算问题。题目给定n个车站和m条订票申请,每条申请包含区间[x,y)及乘客数z。需要计算在不超载的情况下(每节车厢最多36人),满足所有乘客...

洛谷P1121题解:动态规划求解环形数组最大子段和问题(附代码注释)

洛谷P1121题解:动态规划求解环形数组最大子段和问题(附代码注释)

一、题目解读洛谷P1121题要求求解环形数组的最大子段和,即在一个环形数组中找到一个连续子段,使其元素和最大。环形数组的特殊性在于首尾元素可相连,需考虑线性子段与跨越首尾的环形子段两种情况。二、解题思...

发表评论

访客

看不清,换一张

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