会场安排问题(贪心)

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可以利用之前的会场,而不需要开辟新的会场。

 

posted @ 2018-04-07 21:49  王陸  阅读(1877)  评论(0编辑  收藏  举报