会场安排问题(贪心)
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
解题思路:这是一道贪心题,比起之前的会场安排问题,这道题的问题在于如果一场会议于之前的会议冲突,不一定需要重新安排一个新的会场,还有可能再其他的会场上,与其他的会议不重合,这样就不需要开辟新的会场。贪心策略,按会议开始的顺序升序,对每一个成员都分别遍历一遍,找出可以安排在一个会场的会议(即会议不会出现重合),就划分到一个会场中,最后看看一共有多少个集合就要有多少个会场。这里我使用vis数组来控制会议的遍历,被划分到某个集合的会议将不会再次出现。其实我更喜欢将这一种算法称之为剥离算法(有点筛法的意思?),第一次会将安排在第一个会场的所有会议划分为一个集合,第二次安排第二个会场,第三第四次。。。。直到安排完所有的会议。
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n; struct node { int s; int e; } a[10010]; int vis[10010];///标记数组 int my_cmp(node a,node b) { if(a.s==b.s) { return a.e<b.e; } return a.s<b.s; } int main() { int i,j,counts; int t; scanf("%d",&n); counts=0; for(i=0; i<n; i++) { scanf("%d%d",&a[i].s,&a[i].e); vis[i]=1; } sort(a,a+n,my_cmp); for(i=0; i<n; i++) { t=i; if(vis[i])//没有被划分集合 { for(j=i+1; j<n; j++) { if(vis[j]&&a[j].s>=a[t].e) { t=j; //记录当前会场的序号 vis[j]=0;//划分到统一集合中 } } counts++;///安排到一个会场中 } } printf("%d\n",counts); return 0; }
//最近看同学代码,又发现了一个贪心解法:
#include <iostream> #include <algorithm> using namespace std; int main() { int n; int cnt=0;; cin >> n; int s[10010];//会议开始时间 int e[10010];//会议终止时间 for(int i = 0; i < n; i++) { cin >> s[i] >> e[i]; } sort(s,s+n); sort(e,e+n); int j = 0; for(int i = 0; i < n; i++) { if(s[i] < e[j]) { cnt++; } else { j++; } } cout << cnt << endl; return 0; }
将会议开始时间和结束时间都排序,这时候会议的开始时间和结束时间都是升序的。遍历会议的开始时间,如果有会议i的开始时间小于某会议j的结束时间,那么该会议i一定是需要开辟一个新会场的,而当会议i开始时间大于某会议j的结束时间,该会议i可以利用之前的会场,而不需要开辟新的会场。
本文作者:王陸
本文链接:https://www.cnblogs.com/wkfvawl/p/8735108.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步