算法导论16章贪心算法习题活动教室分配问题(区间图着色问题)分析详解与代码实现

本文介绍了如何利用贪心策略和小顶堆优化活动安排,确保最少教室使用,以Dart为例提供了详细代码实现。
一、题目

在算法导论第三版的第16章贪心算法的思考题16.1-4中,作者提出了这样一个问题:

二、初步分析与具体案例

看到这个题目,第一时间的想法是用教程中的贪心算法进行循环,但这不是最佳的算法。不仅时间复杂度为O(n^{2}),且并不能得到最优解。比如对于如下活动:

会得出需要3个教室,活动安排为:

Room1: [1,4), [6,7)

Room2: [2,5)

Room3: [4,8)

而最优解只需2个教室:

Room1: [1,4), [4,8)

Room2: [2,5),[6,7)

具体解释如下,我就不翻译了:

三、正确的解法

那么,正确的解法是什么呢?在网上搜了很多博客,写的不是很明白,有的代码逻辑也不对,因此给出笔者参考各种文章及教程答案后自己的实现。

核心算法一句话概括如下:

对活动按开始时间升序排序,依次迭代;对已安排活动的教室列表按照可用时间创建一个小顶堆,每次有新活动时,判断堆顶的教室是否可用,可用则用,否则开辟一个新教室安排活动,并将该教室加入小顶堆。(也可用优先队列、有序数组实现小顶堆同样的功能)。

第一步:对活动排序

先对所有的活动按照开始时间升序排序。注意,这里和书上教程例子中的按结束时间排序就不同了。这里要用到排序,快排吧,时间成本 O(n\lg n).

因为按照正常的思维,我们安排一个活动时,也是看这个活动什么时间开始。结合着下面看。

第二步:安排合适的教室

这一步很关键,并且有几种情况,还要引入新的数据结构小顶堆。

Case 1:安排第一个活动,也即现在所有的教室都是可用的。这时随便选取一个教室即可,然后把这个教室的可用时间更新为该活动的结束时间。

Case 2:安排第 m 个活动,且原来已经有一些教室被安排了活动,假设这些教室组成了列表busy_list。由于题目让求的是最小的教室数量,那么要充分利用已经被安排过活动的教室。因此,这一步的关键在于,将所有被安排过活动的教室的可用时间做升序排序。排在首位的是最早释放的,我们假设该教室的编号为R1。然后和活动m的开始时间相比:

如果m的开始时间大于等于R1的可用时间(也即此时R1的上个活动已结束),则将m安排进R1的活动列表,同时更新R1的可用时间,并重新对 busy_list 按照可用时间做升序排序(这样保证每次总是选到最早释放的教室,让教室空置时间尽量的少)。

如果m的开始时间小于R1的可用时间,由于 busy_list 是按升序排序的,那么其他活动教室当前更不可用。此时,开辟一个新的教室R_m,并将m安排进

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值