最简单讲解贪心求解活动安排时间问题

最简单讲解贪心求解活动安排时间问题

假设有一个需要使用某一资源的n个活动所组成的集合S,S={1,…,n}。该资源任何时刻只能被一个活动所占用,活动i有一个开始时间bi和结束时间ei(bi<ei),其执行时间为ei-bi,假设最早活动执行时间为0。一旦某个活动开始执行,中间不能被打断,直到其执行完毕。若活动i和活动j有bi≥ej或bj≥ei,则称这两个活动兼容。设计算法求一种最优活动安排方案,使得所有安排的活动个数最多

关于贪心算法和问题就不在赘述了,下面用最简单的方式进行分析,只要看完,必定搞懂

要满足安排的活动最多,有两个很重要的因素

  • 每个活动所占时间
  • 相邻两个活动间隔
    最后安排的活动保证间隔最短,endTIme-beginTime最小就是最优安排

保证每次安排一个活动后,剩余的时间最长(贪心法的选择核心:使剩余的时间段可安排极大化,尽可能安排更多活动)
最简单的办法就是先进行排序,根据endTime进行升序排列,这里可以用sort()函数进行。

不懂sort()用法的可以参考博客 ,建议先了解,有基础才能弄得明白

//伪代码
sort(开始索引,结束索引,[排序方式])
//这里选择降序排列
两种方法实现
bool cmp_1(const ActivityInfo &a, ActivityInfo &b) {
	return a.endTime<=a.startTime;
}

bool cmp_2(const ActivityInfo &a ,ActivityInfo &b){
	if(a.endtime<=a.startTime){
		return ture;
	}else{
		return false;
	}
}

注意引库 algorithm

选择不冲突的活动存入数组中

 int currentActivity = 0, count = 0;              
    int noConflictActivityIndex[100];             
    noConflictActivityIndex[count] = act[0].index;   //将第一个活动放入数组
    for (int j = 1; j < activityGroups; j ++) {
        if (act[j].startTime >= act[currentActivity].endTime) {
            currentActivity = j;
            noConflictActivityIndex[++count] = act[j].index;    //记下不冲突活动的编码
        }
    }

遍历输出

	cout<<"一共安排活动数:"<<count+1<<endl;
    for (int k = 0; k <= count; k ++) {
        cout << noConflictActivityIndex[k] << ' ';
    }
    delete[] act;                                   //释放资源
    system("pause");
    return 0;

全部代码

#include <iostream>
#include <algorithm>
using namespace std;
struct ActivityInfo {                 //单个活动的信息节点
    int index;                      //活动编号
    int startTime;                  //活动开始时间
    int endTime;                    //活动结束时间
};
bool cmp(const ActivityInfo &a, ActivityInfo &b);
int main()

{	
	cout<<"请输入活动数,及信息"<<endl;
    int activityGroups = 0;                          //所有的活动的组数
    cin >> activityGroups;
    ActivityInfo *act = new ActivityInfo[activityGroups];//开辟活动数组
    for (int i = 0; i < activityGroups; i ++) {
        //输入所有活动的信息
        cin >> act[i].index >> act[i].startTime 
            >> act[i].endTime;
    }
    //对所有活动按照endtime升序排序
    sort(act, act + activityGroups, cmp);
    //贪心算法:只要下一个活动的开始时间在当前活动结束时间之后则这两个活动相容
    //把此活动加入符合条件的集合
    int currentActivity = 0, count = 0;               //当前符合要求的活动
    int noConflictActivityIndex[100];               //此处用一个常量来定义
    noConflictActivityIndex[count] = act[0].index;   //将第一个活动放入数组
    for (int j = 1; j < activityGroups; j ++) {
        if (act[j].startTime >= act[currentActivity].endTime) {
            currentActivity = j;
            noConflictActivityIndex[++count] = act[j].index;    //记下不冲突活动的编码
        }
    }
    //输出
	cout<<"一共安排活动数:"<<count+1<<endl;
    for (int k = 0; k <= count; k ++) {
        cout << noConflictActivityIndex[k] << ' ';
    }
    delete[] act;                                   //释放资源
    system("pause");
    return 0;
}
bool cmp(const ActivityInfo &a, ActivityInfo &b) {
    //比较函数,作为sort的第三个参数,实现升序排序
    //if (a.endTime <= b.endTime) {
      //  return true;
   // }
   // return false;
	return a.endTime<=a.startTime;
}

运行结果
上面是对这个问题最简单的讲解了,对你有帮助留下足迹吧。

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值