文章目录
- ⭐例题
- 🚩题意与思路
 
- ⭐返回贪心
- 🚩原理(反悔池)
- 🚩落实到题
- 🚩AC code
 
- ⭐练习题
- ⭐END
- 🌟交流方式
 
⭐例题
经典例题:
871. 最低加油次数
🚩题意与思路
题意:
从 0 开始,给出目的地target和其实油量startFuel。
给出路途中的加油站的坐标和加油量(假设油箱可以无穷大,但每站只能加一次)。
问是否可以到达目的地。
很显然每个加油站都符合“加油”和“不加油”两个属性。很容易想到01背包。
对于本题的数据范围 (5e2) 来说可以使用01背包来处理,但若数据范围增大 (1e4, 1e5),则会超时。
且本文不是为了讲动规的,因此不多介绍,但还是给出ac的示例代码。
一维 01背包 + 贪心
二维 01背包
⭐返回贪心
🚩原理(反悔池)
准备一个池子,称作反悔池,池中缓存在遍历过程中不断遇到的可选项作为备用资源。
在后续的遍历中,当需要资源的时候,不断的从池中获取,直到满足要求。
基本的原则就如此。
当然这个池子中的值,可以是已经选择了的,也可以是未选择的。都是基于具体题意而言的。
池的数据结构也是基于题目而言比较多样,一般都是堆,栈,队列等可进可出的数据结构。
🚩落实到题
对于本题(871. 最低加油次数),我们用一个堆来进行维护。
使用堆我们可以每次获得池中的最值,也就是我们每次能获得的最大加油量。
到达一个加油站储一次油(加入反悔堆中)。当我们不断要走下一步时,判断是否需要从反悔堆中获得之前没有获取的油。
当堆空了,且未到达目标时就是return -1;。
🚩AC code
当然写法比较多样。
同一种思路或原理,笔者看了下以前的代码发现和现在的实现还是有一定差异的。
下方代码可以AC。
class Solution {
public:
    int minRefuelStops(int target, int startFuel,
                       vector<vector<int>>& stations) {
        // 按照距离从小到达排序
        sort(stations.begin(), stations.end());
        int sum = startFuel;
        // 存储可能可以需要的油
        // 大顶堆,油多的在top
        // 贪心,每次获取经过地点中最大的
        priority_queue<int> pool;
        for (int i = 0; i < stations.size(); i += 1) {
            const int pos = stations[i][0];
            const int value = stations[i][1];
            // 位置>油箱的历史总量油
            // 需要从我们的除油池中获取
            while (sum < pos && !pool.empty()) {
                sum += pool.top();
                pool.pop();
            }
            if (sum < pos) {
                return -1;
            }
            // 当前这个点可以到,储油
            pool.push(value);
            if (sum >= target) {
                return (i + 1) - pool.size();
            }
        }
        while (sum < target && !pool.empty()) {
            sum += pool.top();
            pool.pop();
        }
        if (sum < target) {
            return -1;
        } else {
            return stations.size() - pool.size();
        }
    }
};
⭐练习题
ref:
分享丨【题单】常用数据结构(前缀和/差分/栈/队列/堆/字典树/并查集/树状数组/线段树) - 力扣(LeetCode)
§5.5 反悔堆
-  630. 课程表 III 
-  871. 最低加油次数 2074 
-  1388. 3n 块披萨 2410 
-  1642. 可以到达的最远建筑 1962 
-  2813. 子序列最大优雅度 2582 
-  3049. 标记所有下标的最早秒数 II 3111 
-  LCP 30. 魔塔游戏 
⭐END
🌟交流方式
⭐交流方式⭐ |C/C++|算法|设计模式|软件架构-CSDN社区
关注我,学习更多C/C++,python,算法,软件工程,计算机知识
B站:
👨💻主页:天赐细莲 bilibili






![[Algorithm][贪心][合并区间][无重叠区间][用最少数量的箭引爆气球]详细讲解](https://i-blog.csdnimg.cn/direct/27bbfd48a78a44e189f6e447bb1efd60.png)













