问题背景:
所谓“钟点秘书”,是指年轻白领女性利用工余时间为客户提供秘书服务,并按钟点收取酬金。“钟点秘书”为客户提供有偿服务的方式一般是:采用电话、电传、上网等“遥控”式
服务,或亲自到客户公司处理部分业务。其服务对象主要有三类:一是外地前来考察商务经营、项目投资的商人或政要人员,他们由于初来乍到,急需有经验和熟悉本地情况的秘书帮忙;二是前来开展短暂商务活动,或召开小型资讯发布会的国外客商;三是本地一些请不起长期秘书的企、事业单位。这些客户普遍认为:请“钟点秘书”,一则可免去专门租楼请人的大笔开销;二则可根据开展的商务活动请有某方面专长的可用人才;三则由于对方是临时雇用关系,工作效率往往比固定的秘书更高。据调查,在上海“钟点秘书”的行情日趋看好。对此,业内人士认为:为了便于管理,各大城市有必要组建若干家“钟点秘书服务公司”,通过会员制的形式,为众多客户提供规范、优良、全面的服务,这也是建设国际化大都市所必需的。某跨国公司总裁正分身无术,为一大堆会议时间表焦头烂额,希望高级钟点秘书能做出合理的安排,能在有限的时间内召开更多的会议。
问题分析:
这是一个典型的会议安排问题,会议安排的目的是能在有限的时间内召开更多的会议
(任何两个会议不能同时进行)。在会议安排中,每个会议 i 都有起始时间 bi 和结束时间 ei,且 bi<ei,即一个会议进行的时间为半开区间[bi,ei)。如果[bi,ei)与[bj,ej)均在“有限的时间内”,且不相交,则称会议 i 与会议 j 相容的。也就是说,当 bi≥ej 或 bj≥ei 时,会议 i与会议 j 相容。会议安排问题要求在所给的会议集合中选出最大的相容活动子集,即尽可能在有限的时间内召开更多的会议。在这个问题中,“有限的时间内(这段时间应该是连续的)”是其中的一个限制条件,也应该是有一个起始时间和一个结束时间(简单化,起始时间可以是会议最早开始的时间,结束时间可以是会议最晚结束的时间),任务就是实现召开更多的满足在这个“有限的时间内”等待安排的会议。
算法设计:
(1)初始化:将 n 个会议的开始时间、结束时间存放在结构体数组中(想一想,为什么
不用两个一维数组分别存储?),如果需要知道选中了哪些会议,还需要在结构体中增加会议编号,然后按结束时间从小到大排序(非递减),结束时间相等时,按开始时间从大到小排序(非递增);
(2)根据贪心策略就是选择第一个具有最早结束时间的会议,用 last 记录刚选中会议的
结束时间;
(3)选择第一个会议之后,依次从剩下未安排的会议中选择,如果会议 i 开始时间大于
等于最后一个选中的会议的结束时间 last,那么会议 i 与已选中的会议相容,可以安排,更新 last 为刚选中会议的结束时间;否则,舍弃会议 i,检查下一个会议是否可以安排。
通俗讲:先将数据存到结构体中,用结束时间从小到大排序(若结束时间相同,以开始时间由大到小排序),之后再次基础上再判断开始时间;在会议按结束时间非递减排序的基础上,首先选中第一个会议,用 last 变量记录刚刚被选中会议的结束时间。下一个会议的开始时间与 last 比较,如果大于等于 last,则选中。每次选中一个会议,更新 last 为最后一个被选中会议的结束时间,被选中的会议数counter加 1;如果会议的开始时间不大于等于 last,继续考查下一个会议,直到所有会议考查完毕。最后返回counter即可;
代码如下:
#include <iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;
struct meet{
int begin1;
int end1;
int number;
}a[1014];
bool beyond(meet a,meet b){
if(a.end1 == b.end1) return a.begin1>b.begin1;
return a.end1<b.end1;
}
int main()
{
int all;
int start,stop;
int last;
int counter=1;
scanf("%d",&all);
for(int i=0;i<all;i++){
scanf("%d",&a[i].begin1);
scanf("%d",&a[i].end1);
a[i].number = i+1;
}
sort(a,a+all,beyond);
last = a[0].end1;
for(int j=1;j<all;j++){
if(a[j].begin1 >= last){
counter ++;
last = a[j].end1;
}
}
printf("%d",counter);
return 0;
}