630. Course Schedule III - Hard

本文探讨了一种在线课程安排算法,旨在最大化可参加的课程数量。通过分析课程的持续时间和截止日期,采用贪心策略进行排序和选择。文章详细解释了算法思路,并给出了具体实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description

There are n different online courses numbered from 1 to n. Each course has some duration(course length) t and closed on dth day. A course should be taken continuously for t days and must be finished before or on the dth day. You will start at the 1st day.

Given n online courses represented by pairs (t,d), your task is to find the maximal number of courses that can be taken.

Example:
Input: [[100, 200], [200, 1300], [1000, 1250], [2000, 3200]]
Output: 3

Analyze

我course schedule又回来了!
有一个简单版的问题,条件改为课程的开始结束时间固定,你不可以提前上课。这个问题的限制多了,解就比较容易找,很明显的贪心算法——按开始时间排序,最早结束时间优先,冲突课程忽略。
对于这道题,我尝试按照最迟开始时间排序然后在冲突课程中选择一个更早结束的,只要在冲突范围外的课程就先不予考虑。但提交后发现这不是正确解法,比如按照这种策略选了一个周期很长的课,可是它的冲突范围之外有好几个很短的课互相冲突,由于前面占去了很长的时间只能从中选一个。那当初选那门长长的课就不如提前上几门短的课。
没时间继续想了,赶紧看别人的Discuss。

Code

取的是讨论区最高票C++解法,然而会有Runtime Error,加上一句判断才对:
if(courses[i][0] > courses[i][1]) continue;

算法解释如下:
First, we sort courses by the end date, this way, when we’re iterating through the courses, we can switch out any previous course with the current one without worrying about end date.
Next, we iterate through each course, if we have enough days, we’ll add it to our multiset. If we don’t have enough days, then we can either ignore this course, or we can use it to replace a longer course we added earlier.

My final consideration was when we replace a longer course with a much shorter one, does that mean we’ll have enough room to take some courses previously ignored for being too long?
The answer is no, because any courses we missed would be longer than what’s in multiset cls. So the increase in number of days cannot be larger than the largest element in cls, and certainly will be less than a previously ignored course which has to be even longer.

class Solution {
public:
    int scheduleCourse(vector<vector<int>>& courses) {
        sort(courses.begin(),courses.end(),
            [](vector<int> a, vector<int> b){return a.back()<b.back();});            
        multiset<int> cls;
        int cursum=0;
        for (int i=0; i<courses.size(); i++) {
            if(courses[i][0] > courses[i][1]) continue;
            if (cursum+courses[i].front()<=courses[i].back()) {
                cls.insert(courses[i].front());
                cursum+=courses[i].front();
            } else if (*cls.rbegin()>courses[i].front()) {
                cursum+=courses[i].front()-*cls.rbegin();
                cls.erase(--cls.end());
                cls.insert(courses[i].front());
            }
        }
        return cls.size();
    }
};

Summary

觉得这道题折射出了人生哲理。
我就是一下没想到选了的课还可以退啊!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值