hihoCoder太阁最新面经算法竞赛题解(4)

本文介绍了一种简单的任务调度算法,用于解决多个任务在不同时间段内的最优机器分配问题。通过计算最大冲突子集,即在同一时间段内无法共存的任务集合,得出所需最小机器数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目来源:

    HihoCoder1309

题目要求:

    给定N项任务的起至时间(S1,E1)(S2, E2), ..., (SN, EN), 计算最少需要多少台机器才能按时完成所有任务。

    同一时间一台机器上最多进行一项任务,并且一项任务必须从头到尾保持在一台机器上进行。任务切换不需要时间。

解答:

   本题比较简单。由于某些任务之间的时间具有交集,因此不能同时运行在同一台机器。基于这样的思路,只要找出所有任务中的“最大冲突子集”就可以得到答案,所谓“最大冲突子集”是指从所有的任务中选择部分任务构成一个子集,而在该子集中的任意两个任务都不能运行在同一台机器。
    得到最大冲突子集后,需要的机器数目就是最大冲突子集包含的任务的数目。这个结论是显而易见的,可以按照以下的思路验证其正确性:首先不论如何分配任务,处于同一个最大冲突子集的任务一定不能安排在同一台机器中,假设计算得到的最大冲突子集记作M,容量为K,并将这个K个任务记作m[1],m[2], ...m[K],此时对于子集中的K个任务需要K台机器,每台机器安排一个任务,然后对剩余的N-K个任务进行分配,这里将这N-K个任务记作t[1], t[2], ...t[N-K],显然,对于剩余的N-K个任务中的每一个任务t[i],包含在S中的K个任务中一定存在一个任务m[j]t[i]不会发生冲突,否则,如果t[i]M中所有的任务都发生冲突,那么将t[i]假如到集合S中就可以得到容量更大的冲突子集,这与“M是最大冲突子集”相矛盾。因此,对于每一个任务t[i],在为其安排运行的机器时,一定不会使机器的数目增加。因此,最少需要的机器数就是最大冲突子集的容量K
    接下来的问题是如何找到所有任务的最大冲突子集。根据定义,最大冲突子集中的每一个任务都和子集中其他的所有任务存在冲突,因此,最大冲突子集中的所有任务时间区间的交集一定不为空。基于这样的思路,可以按照这样的思路寻找最大冲突子集:首先设定一个变量w来记录每一个时刻同时运行的任务数目,然后将所有的Si、Ei1≤ix≤N)按递增排序,然后进行遍历,当遍历到一个数据为某个任务的开始时间时,表明当前时刻有新的任务开始,进而,当前正在运行的任务的数目增加,因此,将w1,当遍历到一个数据为某个任务的结束时间时,表明当前是时刻有一项任务结束,进而当前正在运行的任务数目减少,将w1,根据题意,由于任务切换没有冲突和时间消耗,因此,在排序过程中,如果两个数据数值相同,应将结束时间排在前面。最后,在遍历过程中w达到的最大值,就是最大冲突子集的容量,也就是本题的答案。

输入输出格式:

    输入:

第一行一个整数N,(1≤N≤100000),表示任务的数目。 以下N行每行两个整数Si,Ei,(0 ≤Si<Ei≤1000000000),表示任务的起止时间。

输出:
输出一个整数,表示最少的机器数目。
 

程序代码:

package hihocoder;

import java.util.Arrays;
import java.util.Scanner;

/**
 * This is the ACM problem solving program for hihoCoder 1309.
 * 
 * @version 2017-04-26
 * @author Zhang Yufei.
 */
public class HihoCoder1309 {
	/**
	 * Record the task time.
	 */
	private static class TaskTime implements Comparable<TaskTime> {
		static final int START = 0;
		static final int END = 1;
		
		int time;
		int tag;

		@Override
		public int compareTo(TaskTime o) {
			if(time > o.time) {
				return 1;
			} else if(time < o.time) {
				return -1;
			} else {
				if(tag == START) {
					return 1;
				} else {
					return -1;
				}
			}
		}
	}

	/**
	 * Input data.
	 */
	private static int N;

	/**
	 * The task list.
	 */
	private static TaskTime[] times;

	/**
	 * The main program.
	 * 
	 * @param args
	 *            The command-line parameters list.
	 */
	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);

		N = scan.nextInt();

		times = new TaskTime[2 * N];

		for (int i = 0; i < 2 * N; i += 2) {
			times[i] = new TaskTime();
			times[i].time = scan.nextInt();
			times[i].tag = TaskTime.START;
			times[i + 1] = new TaskTime();
			times[i + 1].time = scan.nextInt();
			times[i + 1].tag = TaskTime.END;
		}

		scan.close();

		Arrays.sort(times);
		
		int result = 0;
		int ans = 0;
		for(int i = 0; i < 2 * N; i++) {
			if(times[i].tag == TaskTime.START) {
				ans++;
			} else {
				ans--;
			}
			
			if(result < ans) {
				result = ans;
			}
		}
		
		System.out.println(result);
	}
}

   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值