问题描述
Description
假设要在足够多的会场里安排一批活动,并希望使用尽可能少的会场。设计一个有效的贪心算法进行安排。(这个问题实际上是著名的图着色问题。若将每一个活动作为图的一个顶点,不相容活动间用边相连。使相邻顶点着有不同颜色的最小着色数,相应于要找的最小会场数。)
对于给定的k个待安排的活动,计算使用最少会场的时间表。
Input
输入数据的第一行有1
个正整数k(k≤10000),表示有k个待安排的活动。接下来的k行中,每行有2个正整数,分别表示k个待安排的活动开始时间和结束时间。时间以0
点开始的分钟计。
Output
输出一个整数,表示最少会场数。
Sample Input-1
5 1 23 12 28 25 35 27 80 36 50
Sample Output-1
3
Sample Input-2
6 8 32 18 48 16 82 83 84 39 89 90 98
Sample Output-2
3
思路
这是刚讲完贪心布置的题目,然后我就按贪心做,总是错,才知道用贪心只能局部最优。
**------------------------
具体详情请点击这里,看这篇文章
**------------------------
这题不用贪心,我们先把所有活动按开始时间升序排,然后依次往会场里面放,我们用一维数组a表示会场,每个数组存的是会场中最后一个活动的结束时间,我们只需要将活动开始时间与数组值(即最后一个活动结束时间)比较,相容就放进去,不相同就比较其他会场,如果都不行,就开一个新的会场。
AC代码
#include <iostream>
#include <memory.h>
#include <algorithm>
using namespace std;
//活动结构体
struct Activity {
int start;//活动开始时间
int end;//活动结束时间
} activity[10010];//最多有10000个活动,我们多一丢丢
//a[i]存第i个会场最后一个活动结束时间
int a[10010];//假设我们有10010个会场,不一定都会用到
int pointer = 0;//存已经用了多少会场
//按活动开始时间升序排序
bool cmp( Activity a, Activity b ) {
return a.start < b.start;
}
//活动安排函数
void Arrange( int n ) {
int j;
//遍历每一个活动
for( int i = 0; i < n; i++ ) {
//遍历每一个会场,看能不能排
for( j = 0; j <= pointer; j++ ) {
//活动开始时间>=当前会场最后一个活动的结束时间,可以排
if( activity[i].start >= a[j] ) {
//更新数组值,即会场结束时间
a[j] = activity[i].end;
break;
}
}
//遍历所有会场,没有找到空闲的,另外开一个新会场
if( j == pointer + 1 ) {
pointer++;
//新会场数组存活动结束时间
a[pointer] = activity[i].end;
}
}
}
int main() {
int n;
cin >> n;
for( int i = 0; i < n; i++ ) {
cin >> activity[i].start >> activity[i].end;
}
//初始化所有数组值为0,是为了方便第一个活动放入
memset( a, 0, sizeof( 0 ) );
//按活动开始时间升序排序
sort( activity, activity + n, cmp );
Arrange( n );
cout << pointer + 1 << endl;
}
/*
两组测试数据
第一组:
6
8 32
18 48
16 82
83 84
39 89
90 98
第二组:
5
1 23
12 28
25 35
27 80
36 50
*/