会场安排问题(贪心 两种方法)
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 ( n l o g n ) O(nlogn) 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 ", ans); return 0; }
还有一种时间复杂度 O ( n 2 ) O(n^2) O(n2)的方法;
比活动安排问题多出一个数组用来存储会场当前的状况
#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; }
下一篇:
Java 设计模式看这一篇就够了