#C0E2049. 华为OD机试E卷 - 任务最优调度
华为OD机试E卷 - 任务最优调度
题目链接
华为OD机试E卷 - 任务最优调度(Java & Python& JS & C++ & C )
https://blog.csdn.net/banxia_frontend/article/details/142815335
最新华为OD机试
题目描述
给定一个正整数数组表示待系统执行的任务列表,数组的每一个元素代表一个任务,元素的值表示该任务的类型。
请计算执行完所有任务所需的最短时间。
任务执行规则如下:
- 任务可以按任意顺序执行,且每个任务执行耗时间均为1个时间单位。
- 两个同类型的任务之间必须有长度为N个单位的冷却时间,比如N为2时,在时间K执行了类型3的任务,那么K+1和K+2两个时间不能执行类型3任务。
- 系统在任何一个单位时间内都可以执行一个任务,或者等待状态。
说明:数组最大长度为1000,速度最大值1000。
输入描述
第一行记录一个用半角逗号分隔的数组,数组长度不超过1000,数组元素的值不超过1000,
第二行记录任务冷却时间,N为正整数,N<=100。
输出描述
输出为执行完所有任务所需的最短时间。
示例1
输入
2,2,2,3
2
输出
7
说明
时间1:执行类型2任务。 时间2:执行类型3的任务(因为冷却时间为2,所以时间2不能执行类型2的任务)。 时间3:系统等待(仍然在类型2的冷却时间)。 时间4:执行类型2任务。 时间5:系统等待。 时间6:系统等待。 时间7:执行类型2任务。 因此总共耗时7。
解题思路
-
任务类型:输入的数组表示任务列表,每个元素表示一种任务类型,相同的数字表示同一类型的任务。例如,数组
[2, 2, 2, 3]
表示三个类型为2
的任务和一个类型为3
的任务。 -
冷却时间:在相同类型的任务之间必须间隔
N
个时间单位。比如,如果N = 2
,在某个时间执行了类型2
的任务,那么接下来的2
个时间单位内,不能再次执行类型2
的任务。 -
任务执行或等待:系统每个时间单位要么执行任务,要么进入等待状态。即使系统没有可以执行的任务(因为冷却时间的限制),它也会进入等待,直到可以执行下一个任务。
思路
- 优先执行任务:
- 通过排序,使数量最多的任务优先执行,尽可能减少等待时间的数量。
- 在每个时间单位内,尝试执行一个任务(如果没有任务可以执行,则进入等待状态)。
- 冷却机制:
- 对于每个任务,在执行后会设置冷却时间,在此期间不能再次执行同类型的任务。
- 在每个时间单位内,所有任务的冷却时间都会减少,直到冷却期结束。
- 时间计算:
- 通过增加
time
变量,逐步模拟时间的流逝。每次执行任务或等待,time
都会增加。
- 通过增加
Java
import java.util.*;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
// 创建一个 Scanner 对象来获取用户输入
Scanner scanner = new Scanner(System.in);
// 读取第一行输入,将其转换为一个整数列表
String input = scanner.nextLine();
List<Integer> tasks = Arrays.stream(input.split(","))
.map(Integer::parseInt)
.collect(Collectors.toList());
// 读取第二行输入,获取任务间的冷却时间
int waitTime = scanner.nextInt();
// 创建一个哈希映射来存储每种任务的数量
Map<Integer, Integer> count = new HashMap<>();
for (int t : tasks) {
count.put(t, count.getOrDefault(t, 0) + 1);
}
// 创建一个列表来存储每种任务的数量和冷却时间
List<int[]> taskList = new ArrayList<>();
for (Map.Entry<Integer, Integer> entry : count.entrySet()) {
taskList.add(new int[]{entry.getValue(), 0});
}
// 按任务数量对任务列表进行排序,数量多的任务排在前面
Collections.sort(taskList, new Comparator<int[]>() {
@Override
public int compare(int[] a, int[] b) {
return b[0] - a[0];
}
});
// 记录总任务数
int total = tasks.size();
// 初始化时间
int time = 0;
// 当还有任务未执行时,继续执行任务
while (total > 0) {
time++;
boolean flag = true;
for (int[] task : taskList) {
if (flag && task[0] > 0 && task[1] == 0) {
// 如果当前任务可以执行,则执行任务,并更新任务数量和冷却时间
flag = false;
task[0]--;
total--;
task[1] = waitTime;
} else {
// 如果当前任务不能执行,则减少冷却时间
if (task[1] > 0) {
task[1]--;
}
}
}
}
// 打印执行所有任务所需的最短时间
System.out.println(time);
}
}
Python
import sys
input = sys.stdin.readline().strip() # 输入任务序列,以逗号分隔
tasks = [] # 定义任务列表
num = ""
for c in input: # 遍历输入字符串
if c == ',': # 如果遇到逗号
tasks.append(int(num)) # 将当前数字字符串转换为整数并加入任务列表
num = "" # 清空数字字符串
else:
num += c # 否则将当前字符加入数字字符串
if num != "": # 如果数字字符串不为空
tasks.append(int(num)) # 将其转换为整数并加入任务列表
waitTime = int(sys.stdin.readline()) # 输入等待时间
count = {} # 定义字典,用于统计每个任务出现的次数
for t in tasks:
if t in count:
count[t] += 1 # 统计任务出现次数
else:
count[t] = 1
taskList = [] # 定义任务列表,每个任务用一个列表表示,第一个元素为剩余次数,第二个元素为等待时间
for t, c in count.items(): # 遍历字典
taskList.append([c, 0]) # 将每个任务的出现次数加入任务列表
taskList.sort(key=lambda x: x[0], reverse=True) # 按照任务出现次数从大到小排序
total = len(tasks) # 总任务数
time = 0 # 当前时间
while total > 0: # 当还有任务未完成时
time += 1 # 时间加一
flag = True # 标记是否已经有任务开始执行
for task in taskList: # 遍历任务列表
if flag and task[0] > 0 and task[1] == 0: # 如果当前任务未执行且等待时间为零且还未有任务开始执行
flag = False # 将标记设为false,表示已经有任务开始执行
task[0] -= 1 # 当前任务剩余次数减一
total -= 1 # 总任务数减一
task[1] = waitTime # 将当前任务的等待时间设为输入的等待时间
else:
if task[1] > 0: # 如果当前任务正在等待
task[1] -= 1 # 等待时间减一
print(time) # 输出完成所有任务所需的最短时间
JavaScript
const readline = require('readline').createInterface({
input: process.stdin,
output: process.stdout
});
let tasks;
readline.on('line', (line) => {
if (!tasks) {
// 读取任务列表
tasks = line.split(',').map(Number);
} else {
// 读取冷却时间
waitTime = Number(line);
readline.close();
// 创建一个映射来存储每种任务的数量
let count = {};
for (let t of tasks) {
count[t] = (count[t] || 0) + 1;
}
// 创建一个列表来存储每种任务的数量和冷却时间
let taskList = Object.entries(count).map(([k, v]) => [v, 0]);
// 按任务数量对任务列表进行排序,数量多的任务排在前面
taskList.sort((a, b) => b[0] - a[0]);
// 记录总任务数
let total = tasks.length;
// 初始化时间
let time = 0;
// 当还有任务未执行时,继续执行任务
while (total > 0) {
time++;
let flag = true;
for (let task of taskList) {
if (flag && task[0] > 0 && task[1] === 0) {
// 如果当前任务可以执行,则执行任务,并更新任务数量和冷却时间
flag = false;
task[0]--;
total--;
task[1] = waitTime;
} else {
// 如果当前任务不能执行,则减少冷却时间
if (task[1] > 0) {
task[1]--;
}
}
}
}
// 打印执行所有任务所需的最短时间
console.log(time);
}
});
C++
#include <iostream>
#include <vector>
#include <sstream>
#include <algorithm>
#include <map>
using namespace std;
int main() {
// 读取任务列表
vector<int> tasks;
string line;
getline(cin, line);
stringstream ss(line);
for (int t; ss >> t;) {
tasks.push_back(t);
if (ss.peek() == ',') ss.ignore();
}
// 读取冷却时间
int waitTime;
cin >> waitTime;
// 创建一个映射来存储每种任务的数量
map<int, int> count;
for (int t : tasks) {
count[t]++;
}
// 创建一个列表来存储每种任务的数量和冷却时间
vector<pair<int, int>> taskList;
for (auto &entry : count) {
taskList.push_back({entry.second, 0});
}
// 按任务数量对任务列表进行排序,数量多的任务排在前面
sort(taskList.begin(), taskList.end(), greater<pair<int, int>>());
// 记录总任务数
int total = tasks.size();
// 初始化时间
int time = 0;
// 当还有任务未执行时,继续执行任务
while (total > 0) {
time++;
bool flag = true;
for (auto &task : taskList) {
if (flag && task.first > 0 && task.second == 0) {
// 如果当前任务可以执行,则执行任务,并更新任务数量和冷却时间
flag = false;
task.first--;
total--;
task.second = waitTime;
} else {
// 如果当前任务不能执行,则减少冷却时间
if (task.second > 0) {
task.second--;
}
}
}
}
// 打印执行所有任务所需的最短时间
cout << time << endl;
return 0;
}
C语言
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 比较函数,用于排序任务列表
int compare(const void* a, const void* b) {
return ((int*)b)[0] - ((int*)a)[0];
}
int main() {
// 输入任务列表
char input[1000];
fgets(input, sizeof(input), stdin);
// 创建任务数组
int tasks[100], task_count = 0;
char* token = strtok(input, ",");
while (token != NULL) {
tasks[task_count++] = atoi(token);
token = strtok(NULL, ",");
}
// 输入冷却时间
int waitTime;
scanf("%d", &waitTime);
// 统计每种任务的数量
int count[1000] = {0}; // 假设任务编号最大为999
for (int i = 0; i < task_count; i++) {
count[tasks[i]]++;
}
// 创建任务列表
int taskList[100][2], taskList_count = 0;
for (int i = 0; i < 1000; i++) {
if (count[i] > 0) {
taskList[taskList_count][0] = count[i]; // 任务数量
taskList[taskList_count][1] = 0; // 冷却时间
taskList_count++;
}
}
// 按任务数量排序,数量多的任务排在前面
qsort(taskList, taskList_count, sizeof(taskList[0]), compare);
// 总任务数
int total = task_count;
int time = 0;
// 执行任务
while (total > 0) {
time++;
int flag = 1; // 标志位,确保每个时间单位只执行一个任务
for (int i = 0; i < taskList_count; i++) {
if (flag && taskList[i][0] > 0 && taskList[i][1] == 0) {
// 执行任务
flag = 0;
taskList[i][0]--;
total--;
taskList[i][1] = waitTime;
} else {
// 减少冷却时间
if (taskList[i][1] > 0) {
taskList[i][1]--;
}
}
}
}
// 输出总时间
printf("%d\n", time);
return 0;
}
完整用例
用例1
1,2,3
1
用例2
4,4,4
2
用例3
1,1,2,2,3
1
用例4
1,1,1,2,2,2
2
用例5
2,2,2,3
2
用例6
3,1,2,3,2,1
2
用例7
1,1,2,2,3,3
4
用例8
1,1,2,2,3,3
3
用例9
1, 1, 1, 1, 1
5
用例10
1,1,2,2,2,3,3,3,3
2