【华为OD-B卷-打印文件 100分(python、java、c++、js、c)】

【华为OD-B卷-打印文件 100分(python、java、c++、js、c)】

题目

有5台打印机打印文件,每台打印机有自己的待打印队列。
因为打印的文件内容有轻重缓急之分,所以队列中的文件有1~10不同的代先级,其中数字越大优先级越高。
打印机会从自己的待打印队列中选择优先级最高的文件来打印。
如果存在两个优先级一样的文件,则选择最早进入队列的那个文件。
现在请你来模拟这5台打印机的打印过程。

输入描述

  • 每个输入包含1个测试用例,

每个测试用例第一行给出发生事件的数量N(0 < N < 1000)。

接下来有 N 行,分别表示发生的事件。共有如下两种事件:

"IN P NUM",表示有一个拥有优先级 NUM 的文件放到了打印机 P 的待打印队列中。(0< P <= 5, 0 < NUM <= 10); "OUT P",表示打印机 P 进行了一次文件打印,同时该文件从待打印队列中取出。(0 < P <= 5)

输出描述

  • 对于每个测试用例,每次"OUT P"事件,请在一行中输出文件的编号。 如果此时没有文件可以打印,请输出"NULL"。 文件的编号定义为"IN P NUM"事件发生第 x 次,此处待打印文件的编号为x。编号从1开始

用例

用例一:
输入:
复制代码
7
IN 1 1
IN 1 2
IN 1 3
IN 2 1
OUT 1
OUT 2
OUT 2
输出:
复制代码
3
4
NULL
用例二:
输入:
复制代码
5
IN 1 1
IN 1 3
IN 1 1
IN 1 3
OUT 1
输出:
复制代码
2

python解法

  • 解题思路:
  1. 解题思路

    题目回顾

    有 5 台打印机,每台有独立的待打印队列;

    每个队列中的文件具有:

    优先级(1~10),越大越优先;

    先进先出(同优先级按加入顺序);

    两种事件类型:

    "IN P NUM":编号为 x 的文件以优先级 NUM 加入打印机 P 的队列;

    "OUT P":打印机 P 打印优先级最高、加入最早的文件;

    每次 "OUT" 输出打印的文件编号,如果为空输出 "NULL"。

✅ 实现思路

使用 defaultdict(deque) 为每个打印机维护一个队列(打印任务池);

复制代码
每次 "IN P NUM" 事件,将文件加入打印机 P 的队列;

记录:优先级、加入顺序、编号(即事件序号);

每次 "OUT P":

遍历队列中所有任务,按 优先级降序、时间升序 排序;

取出第一个任务(最高优先级 + 最早加入),输出其编号;

将该任务从队列中删除;

维护一个全局编号 idx,自增标记文件编号。
  1. 使用到的算法
    defaultdict(deque) 按打印机编号分类管理队列任务
    自定义排序(lambda) 按优先级(降序)和顺序(升序)选任务
    队列(FIFO) 保证同优先级时,最早加入任务优先出队
python 复制代码
from collections import defaultdict, deque

def get_result(tasks):
    mp = defaultdict(deque)  # 打印机编号 -> 任务队列(deque)
    idx = 1                  # 文件编号,从1开始

    for i, t in enumerate(tasks):  # 遍历每个事件
        if t[0] == 'IN':
            # IN P NUM:t[1]是打印机编号,t[2]是优先级
            # 添加任务 (优先级,加入时间,用于排序),i是当前事件序号,idx是文件编号
            mp[t[1]].append((int(t[2]), i, idx))
            idx += 1  # 文件编号递增

        else:  # OUT P:打印机 P 执行一次打印任务
            lst = list(mp[t[1]])  # 获取打印机 t[1] 的任务列表

            if not lst:
                print('NULL')  # 无任务可打印
                continue

            # 排序规则:优先级降序,加入时间升序
            lst.sort(key=lambda x: (-x[0], x[1]))  # x = (优先级, 时间, 编号)

            top = lst[0]  # 取排序后第一个为要打印的文件

            mp[t[1]].remove(top)  # 从打印机队列中删除它

            print(top[2])  # 输出文件编号

java解法

  • 解题思路
  1. 解题思路

    题目回顾

    有 5台打印机(编号 1~5),每台有独立的待打印队列;

    每个文件有一个优先级(1~10,越大优先级越高);

    每台打印机执行 "OUT" 操作时:

    打印优先级最高的文件;

    如果优先级相同,则选择最早加入的那个;

    文件编号按 "IN" 事件顺序递增,从 1 开始;

    输出每次 "OUT" 操作的文件编号,如果队列为空,输出 "NULL"。

✅ 解法设计

使用 Map<String, List<int[]>> 来存储每台打印机的待打印队列;

复制代码
key 是打印机编号(字符串);

value 是当前打印机上的文件队列,每个文件用 int[]{优先级, 时间戳, 编号} 表示;

"IN P NUM" 操作:加入到指定打印机的队列;

"OUT P" 操作:

遍历打印机 P 的任务队列;

使用 Collections.min() + 自定义比较器,选出优先级高、加入早的文件;

打印编号并从队列中移除;

如果该打印机没有文件,输出 "NULL"。

🧮 2. 使用到的算法与数据结构

Map<String, List<int[]>> 存储每台打印机的任务队列

Collections.min() + Lambda 找出当前打印机队列中应打印的文件

自定义排序 比较优先级(降序)、时间(升序)

ArrayList 动态维护队列,支持随机访问和删除

java 复制代码
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = Integer.parseInt(sc.nextLine());  // 读取事件总数 N
        List<String[]> ls = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            // 每行事件分割成数组 ["IN", "1", "5"] 或 ["OUT", "3"]
            ls.add(sc.nextLine().split(" "));
        }
        run(ls);  // 执行模拟操作
    }

    public static void run(List<String[]> ls) {
        // mp:每台打印机编号 -> 对应任务队列(List<int[]>)
        Map<String, List<int[]>> mp = new HashMap<>();

        int idx = 1; // 文件编号从1开始,每次IN操作后递增

        for (int i = 0; i < ls.size(); i++) {
            String[] t = ls.get(i); // 当前事件数组 t,如 ["IN", "1", "5"]
            if (t[0].equals("IN")) {
                // 获取打印机编号 t[1],优先级 t[2]
                mp.putIfAbsent(t[1], new ArrayList<>()); // 若不存在则新建队列

                // 添加任务到打印机队列:{优先级,事件顺序号,用于时间排序,编号}
                mp.get(t[1]).add(new int[]{Integer.parseInt(t[2]), i, idx++});
            } else {
                // "OUT" 操作:判断打印机是否有任务
                if (!mp.containsKey(t[1]) || mp.get(t[1]).isEmpty()) {
                    System.out.println("NULL"); // 无任务可打印
                } else {
                    List<int[]> lst = mp.get(t[1]); // 获取打印机任务列表

                    // 自定义排序:优先级降序,时间戳升序
                    int[] top = Collections.min(lst, (a, b) -> {
                        if (a[0] != b[0]) return b[0] - a[0]; // 优先级高的排前面
                        return a[1] - b[1]; // 时间早的排前面
                    });

                    lst.remove(top); // 从任务队列中移除被打印的文件
                    System.out.println(top[2]); // 输出文件编号
                }
            }
        }
    }
}

C++解法

  • 解题思路
c++ 复制代码
更新中

C解法

解题思路

c 复制代码
更新中

JS解法

解题思路

javascript 复制代码
更新中

注意:

如果发现代码有用例覆盖不到的情况,欢迎反馈!会在第一时间修正,更新。
解题不易,如对您有帮助,欢迎点赞/收藏

相关推荐
kokotao19 分钟前
使用Java实现Navicat密码的加密与解密
java·开发语言·数据库·mysql
快乐肚皮27 分钟前
深入浅出:Spring Cloud Gateway 扩展点实践指南
java·linux·运维
胡小禾32 分钟前
ES常识9:如何实现同义词映射(搜索)
java·大数据·elasticsearch
蚰蜒螟35 分钟前
jvm安全点(一)openjdk17 c++源码垃圾回收安全点信号函数处理线程阻塞
jvm·c++·安全
caihuayuan51 小时前
使用 Java 开发 Android 应用:Kotlin 与 Java 的混合编程
java·大数据·vue.js·spring boot·课程设计
软件开发-NETKF88881 小时前
JAVA序列化
java
2401_861412141 小时前
Python编程从入门到实践 PDF 高清版
python·pdf
朴素先生在进步1 小时前
Memory-Based AI Responder: Principles, Skills, and Workflows
java