活动调度/活动安排(超详细)

活动调度/活动安排(超详细)

输入要求

第一行为活动的个数 N(1<=N<=1 000 000) 。

接下来 N 行为 Si 和 Fi(0<=Si<Fi<=2 000 000 000) ,分别代表第 i 个活动的开始时间和结束时间。活动 i 的区间段为 [Si,Fi)

输出要求

输出有一行 M ,为所需教室的最小数量。

样例

input

11
1 4
3 5
0 6
5 7
3 8
5 9
6 10
8 11
8 12
2 13
12 14

output

5

题解

求最大相容活动的详解可以参考以下博客

https://blog.csdn.net/ii1245712564/article/details/45420061
https://blog.csdn.net/cyp331203/article/details/43199963

本题为求最少需要的教室数,相当于将所给集合g划分成几个子集合,每个集合都尽量容纳更多的相容活动。

解题方法:
以题目样例为例子,推导过程如下:
在这里插入图片描述

  1. 先将开始时间和结束时间分别从小到大排序。这一步至关重要!
  2. 将排好序的活动按顺序从头开始访问,如果开始时间小于最小的结束时间,那么只能新开一个教室,将该活动分配至教室1,该例子中将活动(0,6)分配到教室1,接着访问下一个活动开始时间,如果它仍然小于最小结束时间,新开教室,该例中依次将活动(1,4)、(2,13)、(3,5)、(3,8)放入教室2、3、4、5。
  3. 继续访问下一个活动开始时间,如果大于或者等于最小的结束时间,那么这个活动就可以放在结束时间最小的活动后面,即将(5,7)放入教室2。
  4. 依次类推,最后即可得最少所需教室数。

代码

如何编程实现以上思路呢?
可以设置一个计数器和一个变量记录这个过程中计数器的最大值。当开始时间小于结束时间,表示这个活动需要新开教室(注意已将时间排好序),计数器加一,如果开始时间大于或等于结束时间,说明不需要新开教室,直接将这个活动加入到这个结束时间的活动后面即可,因为是记录计数器的最大值,所以让计数器减一,依次往下,最后计数器最大值即为答案。

#include<iostream>
#include<algorithm>
#define N 1000005
using namespace std;

int s[N], t[N];
int main() {
	int cnt = 0;//计数器
	int ans = 0;
	int i, j;//游标
	int n;
	cin >> n;
	for (i = 0; i < n; i++) {
		cin >> s[i] >> t[i];
	}

	sort(s, s + n);
	sort(t, t + n);
	i = 0;
	j = 0;
	while (i < n && j < n) {
		//开始时间小于当前最小结束时间
		if (s[i] < t[j]) {
			cnt++;
			i++;//游标移到下一个活动(开始时间列上的活动)
			ans = max(ans, cnt);
		}
		//开始时间大于当前最小结束时间
		else if (s[i] > t[j]) {
			cnt--;
			j++;//游标移到下一个活动(结束时间列上的活动)
		}
		//开始时间等于当前最小结束时间
		else {
			j++;
			i++;//两个游标同时移动,计数器不动

		}
		
	}
	cout << ans << endl;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值