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