zoukankan      html  css  js  c++  java
  • 会场安排问题(贪心)

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

  • 相关阅读:
    Snagit文字提取捕获技巧
    Snagit长截图或完整截图技巧
    Snagit基于图像模板预制图片布局
    Snagit从图片创建视频的技巧
    截图工具Snagit试用免费激活方法
    Camtasia快捷键大全
    Axure RP快捷键指令汇总
    113资讯网:安装程序进入Admin后台出现:SQLSTATE[HY000] [1045] Access denied for user'root'@'localhost' (using password: YES)
    部署LNMP环境——Yum安装(113资讯网)
    会过日子是什么样
  • 原文地址:https://www.cnblogs.com/wkfvawl/p/8735108.html
Copyright © 2011-2022 走看看