题目:单核CPU任务调度
知识点队列优先级队列
时间限制:1s 空间限制:256MB 限定语言:不限
题目描述:
现在有一个CPU和一些任务需要处理,已提前获知每个任务的任务ID、优先级、所需执行时间和到达时间。
CPU同时只能运行一个任务,请编写一个任务调度程序,采用“可抢占优先权调度”调度算法进行任务调度,规则如下:
如果一个任务到来时,CPU是空闲的,则CPU可以运行该任务直到任务执行完毕。但是如果运行中有一个更高优先级的任务到来,则CPU必须暂停当前任务去运行这个优先级更高的任务;
如果一个任务到来时,CPU正在运行一个比它优先级更高的任务时,新到达的任务必须等待;
当CPU空闲时,如果还有任务在等待,CPU会从这些任务中选择一个优先级最高的任务执行,相同优先级的任务选择到达时间最早的任务。
输入描述:
输入有若干行,每一行有四个数字(均小于108),分别为任务ID,任务优先级,执行时间和到达时间。每个任务的任务ID不同,优先级数字越大优先级越高,并且相同优先级的任务不会同时到达。
输入的任务已按照到达时间从小到达排列,并且保证在任何时间,处于等待的任务不超过10000个。
输出描述:
按照任务执行结束的顺序,输出每个任务的任务ID和对应的结束时间。
示例1
输入:
1 3 5 1
2 1 5 10
3 2 7 12
4 3 2 20
5 4 9 21
6 4 2 22
输出:
1 6
3 19
5 30
6 32
4 33
2 35
解题思路:
关键点:使用优先级队列PriorityQueue来放置任务。
1、任务1进来,因为当前队列为空,所以直接加入队列,记录任务开始时间为1
队列中:任务1(1 3 5 1)
2、任务2进来,求出两任务的时间间隙10-1=9,取队列中最上层任务1,所需时间为5,说明时间间隙中可以完成任务,输出第一个任务1 6;更新任务开始时间为10,将任务2放入队列
队列中:任务2(2 1 5 10)
3、任务3进来,求出两任务的时间间隙12-10=2,取队列中最上层任务2,所需时间为5,说明时间间隙中不能完成任务,因为有2个时间的间隙,所有需要更新任务2的所需时间5-2=3;更新任务开始时间为12,将任务3放入队列
队列中:任务3(3 2 7 12)、任务2(2 1 3 10)(任务3的优先级高于任务2)
4、任务4进来,求出两任务的时间间隙20-12=8,取队列中最上层任务3,所需时间为7,说明时间间隙中能完成任务3,输出3 19;而20-19=1,时间剩余1,再取队列最上层任务2,而任务2需要3个时间,所有不能完成,更新所需时间3-1=2;更新任务开始时间为20,将任务2和任务4放入队列
队列中:任务4(4 3 2 20)、任务2(2 1 2 10)(任务4的优先级高于任务2)
5、任务5进来,求出两任务的时间间隙21-20=1,取队列中最上层任务4,所需时间为2,所有不能完成,更新所需时间2-1=1;更新任务开始时间为21;将任务5和任务4放入队列
队列中:任务5(5 4 9 21)、任务4(4 3 1 20)、任务2(2 1 2 10)
6、任务6进来,求出两任务的时间间隙22-21=1,取队列中最上层任务5,所需时间为9,所有不能完成,更新所需时间9-1=8;更新任务开始时间为22;将任务6和任务5放入队列
队列中:任务5(5 4 8 21)、任务6(6 4 2 22)、任务4(4 3 1 20)、任务2(2 1 2 10)
7、遍历队列中的任务:
1)任务5:22+8=30、输出5 30
2)任务6:30+2=32、输出6 32
3)任务4:32+1=33、输出4 33
4)任务2:33+2=35、输出2 35
这个算法只有100分,错误的用例也是非常长,显示不全,有可能是需要使用BigDecimal,大家看看有什么其他问题!
全网最全面的华为OD机试真题汇总,100%原题题库,不需要开会员即可查看全部内容,更多考题请查看真题库。
真题库:https://www.yuque.com/codernav.com/od
代码实现:
package com.codernav.demo.hwod.exam; import java.util.ArrayList; import java.util.List; import java.util.PriorityQueue; import java.util.Scanner; /** * @title 单核CPU任务调度 * @Description 现在有一个CPU和一些任务需要处理,已提前获知每个任务的任务ID、优先级、所需执行时间和到达时间。 * CPU同时只能运行一个任务,请编写一个任务调度程序,采用“可抢占优先权调度”调度算法进行任务调度,规则如下: * 如果一个任务到来时,CPU是空闲的,则CPU可以运行该任务直到任务执行完毕。但是如果运行中有一个更高优先级的任务到来,则CPU必须暂停当前任务去运行这个优先级更高的任务; * 如果一个任务到来时,CPU正在运行一个比它优先级更高的任务时,新到达的任务必须等待; * 当CPU空闲时,如果还有任务在等待,CPU会从这些任务中选择一个优先级最高的任务执行,相同优先级的任务选择到达时间最早的任务。 * @Author 开发者导航 * @website https://codernav.com * @date 2023/5/28 */ public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); List<Task> tasks = new ArrayList<>(); while (input.hasNextInt()) { //因为原题没有输出条件,所以这边使用for循环来完成输出 //for(int i=0; i<8; i++){ int id = input.nextInt(); int p = input.nextInt(); int need = input.nextInt(); int start = input.nextInt(); tasks.add(new Task(id, p, need, start)); } //优先级队列 PriorityQueue<Task> queue = new PriorityQueue<>(); long time = 0; for (Task t : tasks) { //两任务开始的相隔时间 long h = t.start - time; while (!queue.isEmpty() && h > 0) { if (h >= queue.peek().need) { //中间的空余时间满足上一个任务执行 Task tmp = queue.poll(); //执行完上个任务所剩下的时间 h -= tmp.need; //上个任务执行完的时间 time += tmp.need; //输出执行完的任务 System.out.println(tmp.id + " " + time); } else { Task tmp = queue.peek(); //更新任务的所需要时间(减去两任务之间的空余时间) tmp.need -= h; //更新时间 time += h; //没有任务能完成直接退出 break; } } //更新时间 if (time < t.start) time = t.start; //加入优先级队列 queue.add(t); } //根据优先级输出任务 while (!queue.isEmpty()) { Task t = queue.poll(); time += t.need; System.out.println(t.id + " " + time); } } public static class Task implements Comparable<Task> { int id; int p; int need; int start; public Task(int id, int p, int need, int start) { this.id = id; this.p = p; this.need = need; this.start = start; } @Override public int compareTo(Task o) { if (this.p == o.p) { return this.start - o.start; } return o.p - this.p; } } }