leecode每日一题(2022/10/22)

leecode每日一题(2022/10/22)

1235. 规划兼职工作

在这里插入图片描述
(图片来源-leecode官方题解)
profit[i-1]存储的就是第i份工作的报酬,这是官方题解,代码如下:

class Solution {
public:
    int jobScheduling(vector<int> &startTime, vector<int> &endTime, vector<int> &profit) {
        int n = startTime.size();
        vector<vector<int>> jobs(n);
        for (int i = 0; i < n; i++) {
            jobs[i] = {startTime[i], endTime[i], profit[i]};
        }
        sort(jobs.begin(), jobs.end(), [](const vector<int> &job1, const vector<int> &job2) -> bool {
            return job1[1] < job2[1];
        });
        vector<int> dp(n + 1);
        for (int i = 1; i <= n; i++) {
            int k = upper_bound(jobs.begin(), jobs.begin() + i - 1, jobs[i - 1][0], [&](int st, const vector<int> &job) -> bool {
                return st < job[1];
            }) - jobs.begin();
            dp[i] = max(dp[i - 1], dp[k] + jobs[i - 1][2]);
        }
        return dp[n];
    }
};
/*
作者:力扣官方题解
链接:https://leetcode.cn/problems/maximum-profit-in-job-scheduling/solutions/1910416/gui-hua-jian-zhi-gong-zuo-by-leetcode-so-gu0e/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
*/

个人方法

还是按照结束时间排序,但是此时开辟一个time数组,大小为最晚结束时间+1,此时在i时刻time[i],已经到手的最大报酬,比如job1:start1=1,end1=4,profit1=20,那么time[1~3]都为0,因为此时最大报酬maxprofit为0,还没有拿到工资,但是time[4]=20(工作一结束,马上报酬到手)。
如果job2:start2=2,end2=6,profit2=10,那么前面的4个时刻的最大报酬不变,因为对于前4个时刻,job1是最好的(此时还没有job2),但是如果可以工作到第5时刻,也就是job2可以被选,那么最大报酬可能不同,time[5]=maxProfit=20,此时还没有到第6时刻,最大报酬仍是job1,但是到了第六时刻,报酬可能是time[2]+profit2(也就是time[start]前的最大报酬+这份工作的报酬),当然,这个工作可能被选择,也可能不被选择,所以要取max{ maxProfit, time[2]+profit2 },因此,就么迭代下去,就可以得到最终答案,当然,有个测试点过不了,就下面这个点:

[1,2,3,3]
[3,4,5,1000000000]
[50,10,40,70]

可以设一个特判,卡过这个测时间(投机取巧了属实)

class Solution {
public:
    int jobScheduling(vector<int>& startTime, vector<int>& endTime, vector<int>& profit) {
        int len = startTime.size();

        // 记录每个工作的信息
        vector<vector<int>> jobs(len);
        for (int i = 0; i < len; i++) {
            jobs[i] = { startTime[i],endTime[i],profit[i] };
        }

        // 按照每个工作的结束时间升序排序
        sort(jobs.begin(), jobs.end(), [](const vector<int>& a, const vector<int>& b)->bool {
            return a[1] < b[1];
            });

        // 特判点
        if (jobs[len - 1][1] == 1000000000)
            jobs[len - 1][1] = 10;
        // 时间数组
        vector<int> time(jobs[len - 1][1] + 1, 0);

        int maxProfit = 0;  // 记录到某个时刻为止的最大报酬
        time[0] = 0;
        int nowTime = 0;    // 当前的时刻
        for (auto job : jobs) {
            int start = job[0], end = job[1], profit1 = job[2];
            for (; nowTime < end; nowTime++) {  // 当前时刻到这份工作结束时刻的报酬都为当前最大报酬
                time[nowTime] = maxProfit;
            }
            time[end] = max(maxProfit, time[start] + profit1);  // 不选择这份工作的最大报酬和选择这份工作可以得到的报酬,取最大值
            maxProfit = max(maxProfit, time[end]);   // 更新最大报酬
        }
        return time[time.size() - 1];  // 返回最后时刻可以得到的最大报酬
    }
};

不过时间效率和空间效率都不咋地,但是是自己A过的第一个困难的dp。yes!!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值