会场安排问题(贪心 两种方法)

Description

假设要在足够多的会场里安排一批活动,并希望使用尽可能少的会场。设计一个有效的贪心算法进行安排。(这个问题实际上是著名的图着色问题。若将每一个活动作为图的一个顶点,不相容活动间用边相连。使相邻顶点着有不同颜色的最小着色数,相应于要找的最小会场数。) 对于给定的k个待安排的活动,计算使用最少会场的时间表。

Input

输入数据的第一行有1 个正整数k(k≤10000),表示有k个待安排的活动。接下来的k行中,每行有2个正整数,分别表示k个待安排的活动开始时间和结束时间。时间以0 点开始的分钟计。

Output

输出一个整数,表示最少会场数。

Sample Input

5
1 23
12 28
25 35
27 80
36 50

Sample Output

3

将开始时间和结束时间分别存为一个数组

然后进行降序排序

从第i个活动开始时间与第j个活动结束时间作比较

如果开始时间大于等于结束时间,说明不用增加会场,就当第j个活动结束了,然后j++

开始时间小于结束时间时,需要增加会场,ans++,第j个活动可以当还没结束,所以j不用动,直到遇到开始时间大于等于第j个活动结束时间的

算法时间复杂度:$O(nlogn)$

c++,sort:

#include <iostream>
#include <algorithm>

using namespace std;

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);

	int n, i, Begins[10002], Ends[10002];	// Begins开始时间, Ends结束时间
	cin >> n;
	for (i = 0; i < n; i++)
		cin >> Begins[i] >> Ends[i];
	sort(Begins, Begins + n);		// 升序排序
	sort(Ends, Ends + n);			// 升序排序
	int j = 0, ans = 0;
	for (i = 0; i < n; i++)
		if (Begins[i] < Ends[j])	// 如果开始时间小于结束时间, 会场数加1
			ans++;
		else						// 开始时间大于等于结束时间, 会场不用增加, 换下一家活动
			j++;
	cout << ans << endl;
	return 0;
}

c,qsort:

#include <stdio.h>
#include <stdlib.h>

int cmp(const void* a, const void* b)
{
	return *(int *)a - *(int *)b;
}

int main()
{
	int n, i, begins[10002], ends[10002];
	scanf("%d", &n);
	for (i = 0; i < n; i++)
		scanf("%d%d", &begins[i], &ends[i]);
	qsort(begins, n, sizeof(int), cmp);
	qsort(ends, n, sizeof(int), cmp);
	int j = 0, ans = 0;
	for (i = 0; i < n; i++)
		if(begins[i] < ends[j])
			ans++;
		else
			j++;
	printf("%d\n", ans);
	return 0;
}

还有一种时间复杂度$O(n^2)$的方法;

比活动安排问题多出一个数组用来存储会场当前的状况

#include <bits/stdc++.h>

using namespace std;

struct Activity
{
	int begin;			// 开始时间
	int end;			// 结束时间
}activity[10002];		// 活动

bool cmp(Activity a, Activity b)
{
	return a.begin < b.begin;
}

int conference[10002];	// 会场

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	int n;
	cin >> n;
	for (int i = 0; i < n; i++)
		cin >> activity[i].begin >> activity[i].end;
	sort(activity, activity + n, cmp);		// 按开始时间升序排序
	int ans = 0;
	for (int i = 0; i < n; i++)
	{
		int temp = ans;
		for (int j = 0; j <= temp; j++)		// 从已经有的会场找需不需要新会场, 不需要就更新结束时间
		{
			if (activity[i].begin >= conference[j])
			{
				if (conference[j] == 0)		// 需要新会场
					ans++;
				conference[j] = activity[i].end;	// 更新会场结束时间
				break;
			}
		}
	}
	cout << ans << endl;
	return 0;
}

 

posted @ 2020-11-07 00:32  yanhua-tj  阅读(700)  评论(0编辑  收藏  举报