贪心算法 - 会场安排

(1)问题描述:假设要在足够多的会场里安排一批活动,并希望使用尽可能少的会场。前提每个活动都有开始和结束时间,一个会场中多个活动不能交叉进行,只能按次序进行,设计一个有效的贪心算法进行安排。

(2)算法设计:对于给定的 activities 个带安排的活动,计算使用最少会场的时间表;

(3)数据输入:第一行输入待安排的活动数量 activities。接下来 activities 行中,每一行有 2 个整数,分别表示 activities 个待安排的活动的开始和结束时间;

(4)思想:记录每个活动的开始和结束时间,按照升序排列,遍历活动开始【START】和结束【FINISHED】标识,遇到 START,加 1,遇到 FINISHED,减 1,然后遍历活动标识数组,找出最大值即为最少会场数量;

(5)代码展示:

public class MeetingArrange {

    /**
     * 会场开始结束标识
     */
    private static final String START = "start";
    private static final String FINISHED = "finished";

    /**
     * 会场安排的活动数量
     */
    private static Integer activities = 0;

    /**
     * 记录当前最少的会场个数
     */
    private static Integer minMettings = 0;

    /**
     * 记录当前会场的数量
     */
    private static Integer[] nowMettingCount;

    /**
     * 活动安排开始结束时间数组
     */
    private static Integer[] startAndFinishedTime;

    /**
     * 活动安排开始结束标识
     */
    private static String[] flag;

    /**
     * 初始化数据
     */
    private static void initData() {
        Scanner input = new Scanner(System.in);
        System.out.println("请输入安排的活动数量:");
        activities = input.nextInt();
        System.out.println("请输入每个活动开始和结束时间:");
        startAndFinishedTime = new Integer[activities * 2];
        flag = new String[activities * 2];
        nowMettingCount = new Integer[flag.length];
        for (int i = 0; i < activities * 2; i = i + 2) {
            startAndFinishedTime[i] = input.nextInt();      // 活动开始时间
            startAndFinishedTime[i + 1] = input.nextInt();  // 活动结束时间
            flag[i] = START;                                // 活动开始标识
            flag[i + 1] = FINISHED;                         // 活动结束标识
            nowMettingCount[i] = 0;                         // 初始化当前会场数量为 0
        }
    }

    /**
     * 活动起始、结束时间数组升序排列
     */
    private static void sortAsc() {
        Integer temp;
        Integer change = 1;
        String str;
        for (int i = 0; i < startAndFinishedTime.length - 1 && change == 1; i++) {
            change = 0;
            for (int j = 0; j < startAndFinishedTime.length - i - 1; j++) {
                if (startAndFinishedTime[j] > startAndFinishedTime[j + 1]) {
                    // 活动开始和结束时间交换
                    temp = startAndFinishedTime[j];
                    startAndFinishedTime[j] = startAndFinishedTime[j + 1];
                    startAndFinishedTime[j + 1] = temp;

                    // 活动开始和结束标识交换
                    str = flag[j];
                    flag[j] = flag[j + 1];
                    flag[j + 1] = str;

                    change = 1;
                }
            }
        }
    }

    /**
     * 统计最少的会场数量
     * 思想:遇到 START,当前会场数量加 1,遇到 FINISHED,当前会场数量减 1;然后遍历当前会场数量数组,取最大值即为最少会场数
     */
    private static Integer countMinMettings() {
        for (int i = 0; i < flag.length; i++) {
            if (flag[i].equals(START)) {
                minMettings++;
            } else {
                minMettings--;
            }
            nowMettingCount[i] = minMettings;
        }

        // 找出最少的会场数量
        return Stream.of(nowMettingCount).max(Comparator.comparingInt(o -> o)).get();
    }

    public static void main(String[] args) {
        // 初始化数据
        initData();

        // 升序
        sortAsc();
//        Stream.of(startAndFinishedTime).forEach(element -> System.out.print(element + " "));

        // 统计最少的会场数量
        Integer min = countMinMettings();
        System.out.println("最少的会场数量为:" + min);

    }

}

(6)输入输出:

请输入安排的活动数量:
5
请输入每个活动开始和结束时间:
1 23
12 28
25 35
27 80
36 50
最少的会场数量为:3

(7)总结:会场安排完全阐释了贪心算法的核心思想,统计出多个局部最优解,在此局部最优解的集合中,选择一个整体的最优解;

  

posted @ 2020-02-10 18:28  菜鸟的奋斗之路  阅读(1680)  评论(0编辑  收藏  举报