- 贪心基础入门讲解三——活动安排问题二

news/2024/11/8 10:49:43

 

有若干个活动,第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,在一系列厚度变化的过程中,峰值(最大值)就是最多同时进行的活动数,也是我们至少需要的教室数。

 

输入

第一行一个正整数n (n <= 10000)代表活动的个数。
第二行到第(n + 1)行包含n个开始时间和结束时间。
开始时间严格小于结束时间,并且时间都是非负整数,小于1000000000
输出
 
一行包含一个整数表示最少教室的个数。
 
输入示例

3
1 2
3 4
2 9

输出示例

2
 
请选取你熟悉的语言,并在下面的代码框中完成你的程序,注意数据范围,最终结果会造成Int32溢出,这样会输出错误的答案。
不同语言如何处理输入输出,请查看下面的语言说明。
#include<cstdio>  
#include<algorithm>  
using namespace std;  
struct node  
{  
    long long str;  
    long long end;  
}arr[10000+11];  
bool cmp(node a,node b)  
{  
    if(a.str==b.str)  
        return a.end<b.end;  
    return a.str<b.str;  
}  
long long b[10000+11];   
int main()  
{  
    int n;  
    scanf("%d",&n);  
    for(int i=0;i<n;++i)  
        scanf("%lld%lld",&arr[i].str,&arr[i].end);  
    sort(arr,arr+n,cmp);  
    b[0]=arr[0].end;//记录结束的时间  
    int i,j;  
    long long sum=1;  
    for(i=1;i<n;++i)  
    {  
        for(j=0;j<sum;++j)   
        {  
            if(arr[i].str>=b[j])//成立代表可以用这个教室,教室不增加,更新结束时间   
            {  
                b[j]=arr[i].end;  
                break;   
            }   
        }   
        if(j==sum)//代表找不到教室,那就增加教室并更新结束时间   
        {  
            b[sum]=arr[i].end;  
            ++sum;   
        }   
    }  
    printf("%lld\n",sum);   
    return 0;   
} 

 如果对你有所帮助,别忘了加好评哦;么么哒!!下次见!88

转载于:https://www.cnblogs.com/cangT-Tlan/p/6219022.html


http://www.niftyadmin.cn/n/4308600.html

相关文章

【原创】C#搭建足球赛事资料库与预测平台(6) 赔率数据表设计2

本博客所有文章分类的总目录&#xff1a;【总目录】本博客博文总目录-实时更新 开源C#彩票数据资料库系列文章总目录&#xff1a;【目录】C#搭建足球赛事资料库与预测平台与彩票数据分析目录 本篇文章开始将逐步介绍使用C#搭建足球赛事资料库与预测平台的相关细节。还是先从数据…

Android SmsManager(短信管理器),发送短信息

AndroidManifest.xml <uses-permission android:name"android.permission.SEND_SMS"/> <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:ap…

分享一个LiteDB做的简单考试系统辅助工具

凌晨&#xff0c;被安排在公司值班&#xff0c;因为台风“灿鸿”即将登陆&#xff0c;风力太大&#xff0c;办公楼&#xff0c;车间等重要部分需要关注。所以无聊&#xff0c;那就分享一下&#xff0c;今天给朋友临时做的一个小的考试系统辅助工具吧。其实非常小&#xff0c;需…

Android SmsManager 短信群发

AndroidManifest.xml <uses-permission android:name"android.permission.READ_PHONE_STATE" /><uses-permission android:name"android.permission.SEND_SMS" /> list.xml <?xml version"1.0" encoding"UTF-8"?&g…

JavaScipt 源码解析 异步

我们常见的异步操作&#xff1a; 定时器setTimeout postmessage WebWorkor CSS3 动画 XMLHttpRequest HTML5的本地数据 等等… JavaScript要求在与服务器进行交互时要用异步通信&#xff0c;如同AJAX一样。因为是异步模型&#xff0c;所以在调用Transaction游览器提供的本地数据…

.NET平台开源项目速览(10)FluentValidation验证组件深入使用(二)

在上一篇文章&#xff1a;.NET平台开源项目速览(6)FluentValidation验证组件介绍与入门(一) 中&#xff0c;给大家初步介绍了一下FluentValidation验证组件的使用情况。文章从构建间的验证器开始&#xff0c;到最后的结果&#xff0c;以及复杂验证等都做了比较深入的讲解和使用…

EhCache RMI 分布式缓存/缓存集群

EhCache 系统简介 EhCache 是一个纯 Java 的进程内缓存框架&#xff0c;具有快速、精干等特点。 EhCache 的主要特性有&#xff1a; 快速、精干简单&#xff1b;多种缓存策略&#xff1b;缓存数据有两级&#xff1a;内存和磁盘&#xff0c;因此无需担心容量问题&#xff1b;缓存…

谈谈博客园和写博客,以及通过博客遇到的那些人

不知不觉&#xff0c;博客园园龄已经5年11个月了&#xff0c;还曾依稀的记得&#xff0c;那是研究生毕业设计搞完了&#xff0c;有没有什么事情可以做&#xff0c;只能每天背个屌丝的书包去学院机房&#xff0c;狂赚CSDN积分&#xff0c;曾经高峰期的时候CSDN积分达到16000分&a…