会场安排问题(贪心算法Java)

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

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

输出格式:
输出最少会场数。

输入样例:
5
1 23
12 28
25 35
27 80
36 50
输出样例:
在这里给出相应的输出。例如:

3

代码如下,需要解释的部分已经注释了


```java
import java.io.BufferedInputStream;
import java.util.Collections;
import java.util.LinkedList;
import java.util.Scanner;

class party implements Comparable<party> {
	public int begin, end;

	public party(int begin, int end) {
		super();
		this.begin = begin;
		this.end = end;
	}

	/*
	 * 一定要按照开始时间进行排序 例如结束时间都为40,由于没有对开始时间排序,所以是乱序的,假设分别为33、13、14
	 * 上一个会场的结束时间为10,那么此时循环先让开始时间为33的会议衔接上一个会场而不是开始时间为13的会议
	 * 一个空余时间为23,另一个是空余时间为3,显然我们要空余时间短的,这才符合贪心策略(贪!)
	 */
	@Override
	public int compareTo(party o) {
		// TODO Auto-generated method stub
		return this.begin - o.begin;
	}
}

public class Main {
	public static void main(String[] args) {
		@SuppressWarnings("resource")
		Scanner in = new Scanner(new BufferedInputStream(System.in));
		int k = in.nextInt();
		LinkedList<party> l = new LinkedList<party>();

		for (int i = 0; i < k; i++) {
			int b = in.nextInt();
			int e = in.nextInt();
			l.add(new party(b, e));
		}

		// 按照开始时间进行升序排序
		Collections.sort(l);

		int times = 0;
		int temp = 0;
		while (!l.isEmpty()) {
			temp = l.getFirst().end;// 获取队列的第一个元素的结束时间
			l.removeFirst();// 再将它从队列中移除因为它已经没有用了
			times++;/*
					 * 因为这场会议终将是要占据一个会场的,所以先开辟一个,
					 * 如果后面会场的开始时间大于该场的结束时间,那就继续使用这个会场,
					 * 否则这个会场只为这一个活动开辟
					 */

			for (int j = 0; j < l.size(); j++) {// 遍历移除后的会场
				if (temp <= l.get(j).begin) {// 判断能不能和上面移除后的会议共用会场
					temp = l.get(j).end;// 如果可以,更新结束时间,这一步很关键
					l.remove(j);// 移除
					j--;/*
						 * 这一步要好好解释一下, 假如说移除的这个元素位置是在3号,那么他后面元素x的位置为4号,
						 * 因为他已经被移除走了,元素x的位置现在就变成了3号,所以为了能够遍历到元素x,需要将j--
						 */
				}
			}
		}
		System.out.println(times);
	}
}


上面这个方法是自己想出来的,有些复杂。

下面这个是非常简洁的写法,具体思路就是,先将开始时间和结束时间都按升序排序,然后再遍历开始时间,如果某个会议i的开始时间小于某个会议j的结束时间,那么该会议i就要开辟一个会场,否则,就可以继续使用会议j用过的会场,这个想法很巧妙,可以自己在纸上模拟一下过程

import java.io.BufferedInputStream;
import java.util.Arrays;
import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner in = new Scanner(new BufferedInputStream(System.in));
		int k=in.nextInt();
		int[] begin=new int[k];
		int[] end=new int[k];
		
		for(int i=0;i<k;i++) {
			begin[i]=in.nextInt();
			end[i]=in.nextInt();
		}
		//两个都按升序排序
		Arrays.sort(begin);
		Arrays.sort(end);
		
		int times=0;
		int j=0;
		for(int i=0;i<begin.length;i++) {
			if(begin[i]<end[j])
				times++;
			else
				j++;
		}
		System.out.println(times);
	}
}

如果对你有帮助的话,记得点赞或者收藏嗷(:

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值