0-1背包问题(物品不可分割)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_41264055/article/details/88074328

问题背景:

所谓“钟点秘书”,是指年轻白领女性利用工余时间为客户提供秘书服务,并按钟点收取酬金。“钟点秘书”为客户提供有偿服务的方式一般是:采用电话、电传、上网等“遥控”式
服务,或亲自到客户公司处理部分业务。其服务对象主要有三类:一是外地前来考察商务经营、项目投资的商人或政要人员,他们由于初来乍到,急需有经验和熟悉本地情况的秘书帮忙;二是前来开展短暂商务活动,或召开小型资讯发布会的国外客商;三是本地一些请不起长期秘书的企、事业单位。这些客户普遍认为:请“钟点秘书”,一则可免去专门租楼请人的大笔开销;二则可根据开展的商务活动请有某方面专长的可用人才;三则由于对方是临时雇用关系,工作效率往往比固定的秘书更高。据调查,在上海“钟点秘书”的行情日趋看好。对此,业内人士认为:为了便于管理,各大城市有必要组建若干家“钟点秘书服务公司”,通过会员制的形式,为众多客户提供规范、优良、全面的服务,这也是建设国际化大都市所必需的。某跨国公司总裁正分身无术,为一大堆会议时间表焦头烂额,希望高级钟点秘书能做出合理的安排,能在有限的时间内召开更多的会议。

问题分析:

这是一个典型的会议安排问题,会议安排的目的是能在有限的时间内召开更多的会议
(任何两个会议不能同时进行)。在会议安排中,每个会议 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;
}

猜你喜欢

转载自blog.csdn.net/qq_41264055/article/details/88074328