【贪心算法】活动安排问题(C++)

一、关于活动安排问题

1. 问题描述:

  • 设有n个活动的集合E={i1,i2,…,in},其中每个活动都要求使用同一资源,如会场等,而在同一时间内只有一个活动能使用这一资源(争用!)。
  • 每个活动i都有一个要求使用该资源的起始时间si和一个结束时间fi,且si<fi
  • 如果选择了活动i,则它在半开时间区间[si, fi)内占用资源。若区间[si, fi)与区间[sj, fj)不相交,则称活动i与活动j是相容的。也就是说,当si≥fj或sj≥fi时,活动i与活动j相容。
  • 活动安排问题就是要在所给的活动集合中选出最大的相容活动子集合(活动数最多)。

2. 问题分析:

该算法的贪心选择的意义:

  • 使剩余的可安排时间段极大化,已便安排尽可能多的相容活动

基本步骤

  1. 用i代表第i个活动,s[i]代表第i个活动开始时间,f[i]代表第i个活动的结束时间,然后按结束时间从早到晚排序
  2. 系统依次检查活动i是否与当前已选择的所有活动相容。若相容,活动i加入已选择活动的集合中,否则,不选择活动i,而继续检查下一活动与集合A中活动的相容性。且若活动i与之相容,则i成为最近加入集合A的活动,并取代活动j的位置。
  3. 挑选出结束时间尽量早的活动,并且满足后一个活动的起始时间晚于前一个活动的结束时间,全部找出这些活动就是最大的相容活动子集合

举个例子

  • 设待安排的11个活动的开始时间和结束时间按结束时间从早到晚排列如下:
    示例1_1
    示例1_2

二、算法实现

1. 贪心算法

//活动安排问题 贪心算法
#include <iostream> 
using namespace std;

void GreedySelector(int n, int s[], int f[], bool A[]);

int main()
{
	const int n = 11;	// 活动个数
	bool A[n + 1];		// true为选择当前活动,false为不选择
	int s[] = { 0,1,3,0,5,3,5,6,8,8,2,12 };		// 下标从1开始,活动开始时间
	int f[] = { 0,4,5,6,7,8,9,10,11,12,13,14 };	// 下标从1开始,活动结束时间

	cout << "各活动的开始时间,结束时间分别为:" << endl;
	for (int i = 1;i <= n;i++)
		cout << "[" << i << "]:" << "(" << s[i] << "," << f[i] << ")" << endl;

	// 贪心算法-活动安排问题
	GreedySelector(n, s, f, A);

	// 输出
	cout << "\n最大相容活动子集为:\n";
	for (int i = 1;i <= n;i++)
		if (A[i])
			cout << "[" << i << "]:" << "(" << s[i] << "," << f[i] << ")" << endl;

	return 0;
}

void GreedySelector(int n, int s[], int f[], bool A[])
{
	A[1] = true;	// 排序后第一个活动即是最早结束活动
	int j = 1;		// 记录最近一次加入A中的活动

	// 依次检查活动i是否与当前已选择的活动相容
	for (int i = 2;i <= n;i++)
	{
		if (s[i] >= f[j])
		{
			A[i] = true;
			j = i;
		}
		else
			A[i] = false;
	}
}

2. 运行结果展示

运行截图

·

三、友情链接~


最后,非常欢迎大家来讨论指正哦!

  • 11
    点赞
  • 92
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值