反悔贪心

遍历时,贪心选择权重最高的值,同时将没有选择的信息保留(优先队列),以便反悔替换
有时存在两个维度,按其中一个维度排序,另一个维度反悔贪心

1. 魔塔游戏

反悔贪心
class Solution {
public:
    int magicTower(vector<int>& nums) {
        long sum = 0;
        for(int n:nums)
            sum+=n;
        if(sum<0) return -1;
        int times = 0; long presum = 1;//初始血量
        priority_queue<int> q;
        for(int i=0;i<nums.size();i++){
            if(nums[i]<0)//如果是小怪,暂存起来
                q.push(-nums[i]);
            presum+=nums[i];//打小怪
            while(presum<1){//打不过选择收益最大的小怪跳过,也可以用if
                presum+=q.top();
                q.pop();
                times++;
            }
        }
        return times;
    }
};

2. 将数组和减半的最少操作数

反悔贪心
class Solution {
public:
    int halveArray(vector<int>& nums) {
        sort(nums.begin(),nums.end(),greater<int>());
        double sum = accumulate(nums.begin(),nums.end(),0ll)*0.5;
        priority_queue<double> q;
        double sub = 0;
        for(int i=0;i<nums.size();i++){
            q.push((double)nums[i]);
            sub += q.top()/2;
            q.push(q.top()/2);
            q.pop();
            if(sub>=sum) return i+1;
        }
        return 0;
    }
};

3. 可以到达的最远建筑

反悔贪心
class Solution {
public:
    int furthestBuilding(vector<int>& heights, int bricks, int ladders) {
        int n = heights.size();
        priority_queue<int, vector<int>, greater<int>> q;
        int sum = 0;
        for (int i = 1; i < n; ++i) {//贪心选择
            int deltaH = heights[i] - heights[i - 1];
            if (deltaH <= 0) continue;//不需要梯子和砖
            q.push(deltaH);//优先使用梯子,暂存以便反悔
            //梯子不够用,反悔前面的一个使用砖头
            if (q.size() > ladders) {
                sum += q.top();
                q.pop();
            }
            if (sum > bricks) return i - 1;
        }
        return n - 1;
    }
};

4. 子序列的最大优雅度

5. 3n块披萨

6. 课程表III

7. 雇佣K名工人的最低成本

8. 最低加油次数

posted @ 2023-08-18 20:11  失控D大白兔  阅读(20)  评论(0编辑  收藏  举报