反悔堆+贪心

在这里插入图片描述

怎么看待这个问题呢,我们每次相加得到的结果小于0时候我们就要从之前相加的负数中选一个最小的负数进行反悔

class Solution {
public:
    int magicTower(vector<int>& nums) {
        priority_queue<int, vector<int>, greater<int>> q; // 升序排序
        int now = 0; int ans = 0;
        int sum = 0;
        for (auto u : nums) {
            if (u < 0) q.push(u);
            now += u;
            if (now < 0) {
                int t = q.top();
                now -= t; q.pop();
                ans++;
            } sum += u;
        }
        return (sum<0)?-1:ans;
    }
};

在这里插入图片描述

这个题目也类似,我们首先肯定要先用砖块,砖块不够的时候我们再考虑拿出之前消耗最大的砖块中回溯一下,不存在满足这个条件下,该使用梯子的时候还能用砖块的,否则我们这个台阶无法过去

class Solution {
public:
    int furthestBuilding(vector<int>& heights, int bricks, int ladders) {
        priority_queue<int, vector<int>, less<int>> q;
        int now = heights[0];
        int n = heights.size();
        int ans = 0;
        for (int i = 1; i < n; i++) {
            if (heights[i] <= now) {
                ans = i; now = heights[i];
            }
            else {
                int cha = heights[i] - now;
                // 如果砖头还有的话
                if (bricks >= cha) {
                    bricks -= cha; q.push(cha);
                    ans = i;
                }
                else {
                    // 砖头不够的话,准备反悔
                    if (ladders <= 0) break;
                    q.push(cha);
                    int t = q.top(); q.pop();
                    if (t == cha) {
                        ladders--; ans = i;
                    }
                    else {
                        bricks += t; bricks -= cha;
                        ladders--; ans = i;
                    }
                }
                now = heights[i];
            }
        }
        return ans;
    }
};

在这里插入图片描述

这个题目当初是要用动态规划写的,给你们看看代码

class Solution {
public:
    int scheduleCourse(vector<vector<int>>& courses) {
        vector<int> dp(N, 0);  int ans = 0;
        int n = courses.size();
        sort(courses.begin(), courses.end(),cmp);
        for (int i = 0; i < n; i++) {
            for (int j = courses[i][1]; j >= courses[i][0]; j--) {
                dp[j] = max(dp[j], dp[j - courses[i][0]] + 1);
                ans = max(ans, dp[j]);
            }
        }
        return ans;
    }
};

但是超时了,呜呜呜呜呜,但是dp的思路还是不错的
这时候我们不得不来点贪心了,我们每次遇到我们目前没办法选但是花费时间比我们之前耗时还大的我们可以选择进行替换

bool cmp(vector<int> a, vector<int> b) {
    return a[1] < b[1];
}
class Solution {
public:
    int scheduleCourse(vector<vector<int>>& courses) {
        vector<int> dp(N, 0);  int ans = 0;
        int n = courses.size();
        sort(courses.begin(), courses.end(),cmp);
        int day = 0;
        priority_queue<int, vector<int>, less<int>> q;
        // 我们必须弄懂一个事实,一个任务多早开始都是ok的
        for (int i = 0; i < n; i++) {
            int dura = courses[i][0], end = courses[i][1];
            if (day + dura <= end) {
                q.push(dura); ans++; day = day + dura;
            }
            else {
                if (q.size() && q.top() > dura) {
                    // 只有之前的空间大于现在的才反悔,不然就没必要,因为我们的数量没变
                    int u = q.top(); q.pop(); q.push(dura);
                    day -= (u - dura);
                }
            }
        }
        return ans;
    }
};

  • 18
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wniuniu_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值