前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >会场安排问题

会场安排问题

作者头像
我没有三颗心脏
发布2018-04-26 16:08:36
1.3K0
发布2018-04-26 16:08:36
举报
文章被收录于专栏:Java WebJava Web

问题描述:

假设要在足够多的会场里安排一批活动,并希望使用尽可能少的会场。设计一个有效的贪心算法进行安排(这个问题实际上是著名的图着色问题。若将每一个活动作为图的一个顶点,不相容活动间用边相连。使相邻顶点着有不同颜色的最小着色数,相应于要找的最小会场数)。

来换一个描述

为了能够更加生动说明问题的整个过程,所以换一个类似的描述来契合《算法图解》一书中的描述。

你没法让这些课都在这间教室上,因为有些课的上课时间有冲突。

你希望这间教室上尽可能多的课。如何选出尽可能多且时间不冲突的课程呢?

这个问题似乎很难,但算法却简单得让人吃惊。具体做法如下:

  • ①选出结束最早的课,它就是要在这间教室上的第一堂课。
  • ②接下来,必须选择第一堂课结束后才开始的课。同样,你选择结束最早的课,这将是要在这间教室上的第二堂课。

重复这样做就能找出答案!下面来试一试。美术课的结束时间最早,为10:00 a.m,因此它就是第一堂课。

接下来的课必须在10:00 a.m后开始,且结束得最早。

英语课不行,因为它的时间与美术课冲突,但数学课满足条件。最后,计算机课与数学课的时间是冲突的,但音乐课可以。

因此将在这间教室上如下三堂课。

贪婪算法很简单:每步都采取最优的做法。在这个示例中,你每次都选择结束最早的课。用专业术语说,就是你每步都选择局部最优解,最终得到的就是全局最优解。听上去有些神奇,但对于这个调度问题上,上述的简单算法找到的就是最优解。

数据输入

第一行有1个正整数k,表示有k个待安排的活动。接下来的k行中,每行有两个正整数,分别表示k个待安排的活动开始时间和活动结束时间。时间以0点开始的分钟计。

由于问题定义上有些纰漏,但通常,我们认为如果上一个活动在t时间结束,下一个活动最早应该在t+1时间开始(上述问题有一定出入)

代码实现

考虑到用户输入并不会按照开始的时间或者结束的时间严格输入,所以我们自己或许要加一个排序算法,这对我们自己遍历也会提供方便:

代码语言:javascript
复制
private static int meeting_problem(int[] startTime,int[] endTime){
    //一组活动数据的最优解
    int maxresult = 1;
    //冒泡排序,对startTime和endTime数据进行排序
    for (int i = 0; i < endTime.length-1; i++) {
        boolean canBreak = true;
        for (int j = 1; j < endTime.length - i; j++) {
            if (endTime[j-1] > endTime[j]) {
                int temp = endTime[j - 1];
                endTime[j-1] = endTime[j];
                endTime[j] = temp;

                int temp2 = startTime[j - 1];
                startTime[j-1] = startTime[j];
                startTime[j] = temp2;
                canBreak = false;
            }
        }
        if (canBreak) {
            break;
        }
    }
    // 记录上一次活动的结束时间
    int key = endTime[0];
    for (int i = 1; i < endTime.length; i++) {
        // 如果活动的开始时间能够大于上一次活动的结束时间
        if (startTime[i] - key >= 1){
            //计数+1
            maxresult ++;
            //保存结束时间
            key = endTime[i];
        }
    }
    return maxresult;
}

结合输入的代码:

代码语言:javascript
复制
public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);
    int num = scanner.nextInt();
    int[] results = new int[num];
    for (int i = 0; i < num; i++) {
        int a = scanner.nextInt();
        int[] startTimes = new int[a];
        int[] endTimes = new int[a];
        for (int j = 0; j < a; j++) {
            startTimes[j] = scanner.nextInt();
            endTimes[j] = scanner.nextInt();
        }
        results[i] = (meeting_problem(startTimes, endTimes));
    }
    for (Integer result:results) {
        System.out.println(result);
    }
}

这里直接引用了 黑白咖 的文章:http://www.jianshu.com/p/0ce92abe862d 中的代码。

另外一种思路

我们也可以通过找最大重叠数来完成,这里不符合贪心策略,所以就不作深入研究。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017.11.25 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 问题描述:
  • 来换一个描述
  • 数据输入
  • 代码实现
  • 另外一种思路
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档