[贪心入门]活动安排问题之二
2015-10-28 08:02
309 查看
有若干个活动,第i个开始时间和结束时间是[Si,fi),活动之间不能交叠,要把活动都安排完,至少需要几个教室?
分析:能否按照之一问题的解法,每个教室安排尽可能多的活动,即按结束时间排序,再贪心选择不冲突的活动,安排一个教室之后,剩余的活动再分配一个教室,继续贪心选择……
反例: A:[1,2) B:[1,4) C:[5,6) D:[3,7)
已经按结束时间排好顺序,我们会选择
教室1: A C
教室2: B
教室3: D
需要3个教室。
但是如果换一种安排方法,我们可以安排AD在一个教室,而BC在另外一个教室,两个教室就够了。
所以之前的贪心策略解决不了这个问题。
怎么办?之前的策略是用一个教室找所有它能安排下的活动,即用教室找活动,我们能不能用活动找教室呢?
策略: 按照开始时间排序优先安排活动,如果冲突,则加一个教室。
简单地理解一下,策略是这样,我们把活动按照开始时间有小到大的顺序排序。假设目前已经分配了k个教室(显然k初始等于0),对于当前这个活动,
(1) 如果它能安排在k个教室里的某一个,则把它安排在其中的任何一个教室里,k不变。
(2) 否则它和每个教室里的活动都冲突,则增加一个教室,安排这个活动。
这个策略是最优么?
我们想像一下k增加1的过程: 因为我们是按照开始时间排序的,意味着当前考虑的这个活动开始的时候,k个教室里都有活动没结束(因为如果有一个教室的活动结束了,我们就可以安排这个活动进入那个教室而不冲突,从而不用增加k)。这就意味着在这个活动开始的时间点,算上目前考虑的这个活动,有(k + 1)个活动正在进行,同一时刻有(k + 1)个活动在进行,无论我们如何安排教室,都至少需要(k + 1)个教室。因为每个教室里不能同时进行两个活动。而我们的策略恰好需要(k + 1)个教室,所以是最优的。
这个策略也告诉我们,如果从时间轴上“宏观”考虑这个问题。考虑每个时间点同时进行的活动个数,作为这个时间点的厚度(把活动开始和结束时间想像成线段,那么每个时间点有多少条线段覆盖它,可以简单理解为“厚度”),我们至少需要最大厚度那么多个教室——因为那时恰好有最大厚度那么多个活动同时进行,而我们这个贪心策略恰好给了我们一个用最大厚度那么多个教室安排全部活动的一个方案。
如果只需要教室的个数,我们可以把所有开始时间和结束时间排序,遇到开始时间就把厚度加1,遇到结束时间就把厚度减1,显然最初始和最后结束时的厚度是0,在一系列厚度变化的过程中,峰值(最大值)就是最多同时进行的活动数,也是我们至少需要的教室数。
最后,我们来提供输入输出数据,由你来写一段程序,实现这个算法,只有写出了正确的程序,才能继续后面的课程。
输入
输出
输入示例
输出示例
参考:
分析:能否按照之一问题的解法,每个教室安排尽可能多的活动,即按结束时间排序,再贪心选择不冲突的活动,安排一个教室之后,剩余的活动再分配一个教室,继续贪心选择……
反例: A:[1,2) B:[1,4) C:[5,6) D:[3,7)
已经按结束时间排好顺序,我们会选择
教室1: A C
教室2: B
教室3: D
需要3个教室。
但是如果换一种安排方法,我们可以安排AD在一个教室,而BC在另外一个教室,两个教室就够了。
所以之前的贪心策略解决不了这个问题。
怎么办?之前的策略是用一个教室找所有它能安排下的活动,即用教室找活动,我们能不能用活动找教室呢?
策略: 按照开始时间排序优先安排活动,如果冲突,则加一个教室。
简单地理解一下,策略是这样,我们把活动按照开始时间有小到大的顺序排序。假设目前已经分配了k个教室(显然k初始等于0),对于当前这个活动,
(1) 如果它能安排在k个教室里的某一个,则把它安排在其中的任何一个教室里,k不变。
(2) 否则它和每个教室里的活动都冲突,则增加一个教室,安排这个活动。
这个策略是最优么?
我们想像一下k增加1的过程: 因为我们是按照开始时间排序的,意味着当前考虑的这个活动开始的时候,k个教室里都有活动没结束(因为如果有一个教室的活动结束了,我们就可以安排这个活动进入那个教室而不冲突,从而不用增加k)。这就意味着在这个活动开始的时间点,算上目前考虑的这个活动,有(k + 1)个活动正在进行,同一时刻有(k + 1)个活动在进行,无论我们如何安排教室,都至少需要(k + 1)个教室。因为每个教室里不能同时进行两个活动。而我们的策略恰好需要(k + 1)个教室,所以是最优的。
这个策略也告诉我们,如果从时间轴上“宏观”考虑这个问题。考虑每个时间点同时进行的活动个数,作为这个时间点的厚度(把活动开始和结束时间想像成线段,那么每个时间点有多少条线段覆盖它,可以简单理解为“厚度”),我们至少需要最大厚度那么多个教室——因为那时恰好有最大厚度那么多个活动同时进行,而我们这个贪心策略恰好给了我们一个用最大厚度那么多个教室安排全部活动的一个方案。
如果只需要教室的个数,我们可以把所有开始时间和结束时间排序,遇到开始时间就把厚度加1,遇到结束时间就把厚度减1,显然最初始和最后结束时的厚度是0,在一系列厚度变化的过程中,峰值(最大值)就是最多同时进行的活动数,也是我们至少需要的教室数。
最后,我们来提供输入输出数据,由你来写一段程序,实现这个算法,只有写出了正确的程序,才能继续后面的课程。
输入
第一行一个正整数n (n <= 10000)代表活动的个数。 第二行到第(n + 1)行包含n个开始时间和结束时间。 开始时间严格小于结束时间,并且时间都是非负整数,小于1000000000
输出
一行包含一个整数表示最少教室的个数。
输入示例
3 1 2 3 4 2 9
输出示例
2
n=int(input()) a=[] for i in range(n): t=list(map(int,input().split())) a.append(t[0])#start a.append(-t[1])#end a.sort(key=lambda i:abs(i)) ans=0 k=0 for i in a: if i>0: k+=1 ans=max(k,ans) else:k-=1 print(ans)
参考:
[离散化]人潮最多的時段( Interval Partitioning Problem )
相关文章推荐
- 不忘初心,方得始终
- HDU 5066 Harry And Physical Teacher(物理题)
- 报酬递减法则
- Jackson转换
- 机器学习、统计分析、数据挖掘、神经网络、人工智能、模式识别之间的关系是什么?
- 装饰设计模式
- 提高生产力在一定程度上是通过创新、通过资源从衰退的旧利用方式向更加富有生产力的新利用方式转移来实现的。另外,生产力的提高也可以通过持续改善现有利用方式中资源的生产力来实现。
- OC基础3--------self // super
- TCP/IP,http,socket,长连接,短连接
- 使用需要用户名和密码访问的samba共享
- TP框架,看完,你就能做一个TP框架做的小项目
- Android RecyclerView之代替ListView与GridView
- Android 应用热修复工具 AndFix
- iOS --- 使用UIImageView来实现倒计时动画
- 新手电商进阶:关于刷单哪些事儿 ,心得、技巧、体会
- OSChina 周三乱弹 —— 有种思念叫忘穿秋裤
- JDBC中一个重要的接口PreparedStatement
- Struts2上传单文件或者多个文件的好处
- 操作符和控制流
- c#向MATLAB传递字符串数组