86.多零件流水线优化问题|Marscode AI刷题

1.题目

问题描述

小C、小U、小R是工厂里的三个工人,他们互相协同制作零件。零件的制作包括三种工序:"加工"、"质检"、"收尾",分别由小C、小U、小R负责。每个零件需要多次进行"加工"和"质检"工序,但只需要进行一次"收尾"工序。每次"加工"完成后,需要进行对应的"质检",只有当质检合格后,才可以开始下一次"加工"。当所有的"加工"和"质检"工序完成后,进行一次"收尾"工序,这样零件制作就算完成了。

小C、小U、小R的工作方式原本非常机械化,他们只能按照既定顺序一个工序一个工序地完成一个零件,比如对于一个零件的工序"加工1、质检1、加工2、质检2、收尾",他们会按顺序逐一完成各自的任务。

老板觉得这样太低效了,于是制定了新的加工方式:小C、小U、小R之间不应该互相等待,当他们因工序等待而被阻塞时,可以直接开始新零件的加工。但是每个工序在进行中不能被打断,必须连贯地完成。

例如,有5个零件,每个零件有7道工序,分别耗时如下:

零件一:10, 10, 10, 10, 10, 10, 20

零件二:10, 10, 10, 10, 10, 10, 20

零件三:10, 10, 10, 10, 10, 10, 20

零件四:10, 10, 10, 10, 10, 10, 20

零件五:10, 10, 10, 10, 10, 10, 20

(每一行的7个数字分别表示"加工1","质检1","加工2","质检2","加工3","质检3","收尾"的耗时)

假设零件按照5、4、3、2、1的优先级开始制作,优化后的工序流程中,小C、小U、小R会更加忙碌,避免空闲。

现在给你n个零件及每个零件的工序耗时,问在经过流程优化后,所有零件加工需要花费的总时间是多少?


测试样例

样例1:

输入:n = 5, parts = [[7, 10, 10, 10, 10, 10, 10, 20], [7, 10, 10, 10, 10, 10, 10, 20], [7, 10, 10, 10, 10, 10, 10, 20], [7, 10, 10, 10, 10, 10, 10, 20], [7, 10, 10, 10, 10, 10, 10, 20]]

输出:200

样例2:

输入:n = 3, parts = [[5, 10, 5, 10, 5, 10], [5, 2, 4, 6, 2, 10], [3, 10, 2, 5]]

输出:57

样例3:

输入:n = 4, parts = [[5, 7, 5, 8, 5, 7], [3, 5, 2, 7], [5, 3, 6, 4, 3, 6], [7, 7, 3, 4, 7, 3, 5, 6]]

输出:60

2.思路

1.数据结构选择

  • 每个零件的工序时间被存储在 parts 数组中,其中每个零件有一个列表,第一个元素表示该零件的工序数,后续元素表示每个工序的耗时。
  • flag 数组用来标记每个工序是否完成。我们用 0 和 1 来表示工序是否已经开始或完成。
  • m1, m2, m3 分别表示“加工”、“质检”和“收尾”阶段的结束时间。

2. 调度模拟流程

  • 优先队列(堆):我们使用一个优先队列(堆)来处理每个工序的时间。每次弹出堆中的最早时间,处理该时间点的工序,并安排下一个工序。
  • 标记数组flag[i][j] 表示第 i 个零件的第 j 个工序是否已完成。初始时所有零件的第一个工序都开始进行。

3. 工序执行顺序

  • 加工工序m1):如果当前时间已经过了某个零件的加工工序,我们会将其加工工序标记为完成,并将下一个加工工序安排进入队列。
  • 质检工序m2):如果当前时间已经过了某个零件的质检工序,我们将安排下一个质检工序。
  • 收尾工序m3):当某个零件的最后一个工序完成时,我们安排收尾工序进入队列。

4. 结束条件

当所有零件的工序都完成时,sum_jobs 会变为 0,意味着所有的工序已经完成,最终时间 time 就是任务结束的时间。

3.代码

import heapq
def solution(n, parts):# Please write your code here# 验证输入的零件数量是否与工序列表的长度一致assert n == len(parts)# 初始化标记数组flag,用来表示每个工序是否已完成flag = [[0 for _ in range(len(part))] for part in parts]# b是每个零件的工序数量(即每个零件的加工数量)b = [part[0] for part in parts]# sum_jobs记录尚未完成的工序数量sum_jobs = sum(b)# a是每个零件各个工序的耗时数据,去掉了第一个工序数量的元素a = [part[1:] for part in parts]# 初始化第一个工序的标记,表示所有零件的第一个工序已经开始for i in range(n):flag[i][0] = 1# 初始时间为0time = 0# m1, m2, m3表示分别进行“加工”、“质检”和“收尾”的结束时间m1, m2, m3 = 0, 0, 0# last1i, last1j表示上一轮“加工”工序的零件索引和工序索引last1i, last1j = -1, -1# last2i, last2j表示上一轮“质检”工序的零件索引和工序索引last2i, last2j = -1, -1# last3i表示上一轮“收尾”工序的零件索引last3i = -1# 使用优先队列(堆)来处理工序的执行时间q = []heapq.heappush(q, 0) # 将0(初始时间)加入队列# 当还有未完成的工序时,持续处理while sum_jobs > 0:time = heapq.heappop(q)# 处理所有在相同时间点需要处理的工序while q and q[0] == time:heapq.heappop(q)# 如果当前时间为m3(“收尾”时间),且有待收尾的工序,则减少未完成工序数量if time == m3 and last3i != -1:sum_jobs -= 1# 如果当前时间为m2(“质检”时间),且质检工序未完成,则开始下一个质检工序if time == m2 and last2i != -1 and last2j != -1:flag[last2i][last2j + 1] = 1 # 标记该零件的质检工序已完成sum_jobs -= 1 # 完成一个工序,减少未完成的工序数量# 如果当前时间大于等于m1(“加工”时间),尝试安排新的加工工序if time >= m1:if time == m1 and last1i != -1 and last1j != -1:flag[last1i][last1j + 1] = 1 # 标记加工工序已完成sum_jobs -= 1 # 完成一个工序,减少未完成的工序数量# 查找下一个可以进行的加工工序found = Falsefor i in range(n):for j in range(0, b[i], 2): # 偶数索引表示加工工序if flag[i][j] == 1 and j != b[i] - 1: # 检查工序是否已完成temi, temj = i, jflag[temi][temj] = 0 # 标记该工序已开始m1 = time + a[temi][temj] # 计算新的加工结束时间last1i, last1j = temi, temj # 记录最新加工工序的位置heapq.heappush(q, m1) # 将加工结束时间加入队列found = Truebreakif found:break# 如果当前时间大于等于m2(“质检”时间),尝试安排新的质检工序if time >= m2:found = Falsefor i in range(n):for j in range(1, b[i], 2):if flag[i][j] == 1:temi, temj = i, jflag[temi][temj] = 0m2 = time + a[temi][temj]last2i, last2j = temi, temjheapq.heappush(q, m2)found = Truebreakif found:break# 如果当前时间大于等于m3(“收尾”时间),开始安排收尾工序if time >= m3:for i in range(n):if flag[i][b[i] - 1] == 1:temi = iflag[temi][b[temi] - 1] = 0 # 标记收尾工序已开始m3 = time + a[temi][b[temi] - 1]last3i = temiheapq.heappush(q, m3)breakreturn timeif __name__ == "__main__":#  You can add more test cases hereparts1 = [[7, 10, 10, 10, 10, 10, 10, 20],[7, 10, 10, 10, 10, 10, 10, 20],[7, 10, 10, 10, 10, 10, 10, 20],[7, 10, 10, 10, 10, 10, 10, 20],[7, 10, 10, 10, 10, 10, 10, 20]]parts2 = [[5, 10, 5, 10, 5, 10],[5, 2, 4, 6, 2, 10],[3, 10, 2, 5]]print(solution(5, parts1) == 200)print(solution(3, parts2) == 57)

heapq 是 Python 内置的一个模块,用于实现堆(heap)数据结构,堆是一种二叉树结构,满足“堆序性质”,可以高效地获取最小(或最大)元素。heapq 模块实现的是一个最小堆(min-heap),即堆顶元素总是最小的。

主要功能

  1. 堆的插入和删除:通过 heapq 提供的函数,可以轻松地维护一个堆,支持插入、删除、获取最小元素等操作。
  2. 优先队列:由于堆可以高效地获取最小元素,所以它通常用于实现优先队列(priority queue),例如在你提供的代码中,堆用于存储和处理不同时间点的工序。

常用函数

  1. heapq.heappush(heap, item)

    向堆中插入一个元素,并保持堆的性质。

    • heap:堆数据结构(列表)
    • item:要插入的元素
    
    import heapq
    heap = [1, 3, 5, 7, 9, 2]
    heapq.heappush(heap, 4)
    print(heap)  # 输出 [1, 3, 2, 7, 9, 5, 4]
  2. heapq.heappop(heap)

    从堆中弹出并返回最小的元素,并重新保持堆的性质。

    • 返回堆中的最小元素,且移除该元素。
    
    import heapq
    heap = [1, 3, 5, 7, 9, 2]
    print(heapq.heappop(heap))  # 输出 1
    print(heap)  # 输出 [2, 3, 5, 7, 9]
  3. heapq.heappushpop(heap, item)

    向堆中插入元素,然后立即弹出并返回堆中最小的元素。这个操作比先插入然后再弹出要高效。

    
    import heapq
    heap = [1, 3, 5, 7, 9, 2]
    print(heapq.heappushpop(heap, 4))  # 输出 1,4 被插入后 1 被弹出
    print(heap)  # 输出 [2, 3, 4, 7, 9, 5]
  4. heapq.heapify(iterable)

    将一个可迭代对象转换成堆。

    • iterable:可以是列表、元组等,转化为堆结构。
    
    import heapq
    heap = [5, 7, 9, 1, 3, 2]
    heapq.heapify(heap)
    print(heap)  # 输出 [1, 3, 2, 7, 5, 9]
  5. heapq.nlargest(n, iterable)

    获取 iterable 中最大的 n 个元素。

    • n:需要返回的元素个数
    • iterable:可以是任何可迭代对象
    
    import heapq
    nums = [1, 3, 5, 7, 9, 2]
    print(heapq.nlargest(3, nums))  # 输出 [9, 7, 5]
  6. heapq.nsmallest(n, iterable)

    获取 iterable 中最小的 n 个元素。

    • n:需要返回的元素个数
    • iterable:可以是任何可迭代对象
    
    import heapq
    nums = [1, 3, 5, 7, 9, 2]
    print(heapq.nsmallest(3, nums))  # 输出 [1, 2, 3]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/21451.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

七星棋牌源码高阶技术指南:6端互通、200+子游戏玩法深度剖析与企业级搭建实战(完全开源)

在棋牌游戏行业高速发展的今天,如何构建一个具备高并发、强稳定性与多功能支持的棋牌游戏系统成为众多开发者和运营团队关注的焦点。七星棋牌全开源修复版源码 凭借其 六端互通、200子游戏玩法、多省区本地化支持,以及 乐豆系统、防沉迷、比赛场、AI智能…

C++和OpenGL实现3D游戏编程【总览】

欢迎来到zhooyu的游戏专栏。 主页网址:【zhooyu】 专栏网址:【C和OpenGL实现3D游戏编程】 🌟🌟🌟这里将通过一个OpenGL实现3D游戏编程实例教程,带大家深入学习OpenGL知识。知识无穷而人力有穷,…

pycharm社区版有个window和arm64版本,到底下载哪一个?还有pycharm官网

首先pycharm官网是这一个。我是在2025年2月16日9:57进入的网站。如果网站还没有更新的话,那么就往下滑一下找到 community Edition,这个就是社区版了免费的。PyCharm:适用于数据科学和 Web 开发的 Python IDE 适用于数据科学和 Web 开发的 Python IDE&am…

GPT-Sovits:语音克隆训练-遇坑解决

前言 本来以为3050完全无法执行GPT-Sovits训练的,但经过实践发现其实是可以,并且仅花费了十数分钟便成功训练和推理验证了自己的语音模型。 官方笔记:GPT-SoVITS指南 语雀 项目地址:https://github.com/RVC-Boss/GPT-SoVITS 本人…

8 SpringBootWeb案例(上): 查询【分页功能(分页插件)】、删除、新增、修改

文章目录 前言:SpringBootWeb案例1. 准备工作1.1 需求&环境搭建1.1.1 需求说明1.1.2 环境搭建1.2 开发规范1.2.1 开发规范-REST(不强求非要这种风格,传统风格有时候更方便)1.2.2 开发规范-统一响应结果和异常处理1.2.3 开发流程2. 部门管理2.1 查询部门2.1.1 原型和需求…

深入了解 DevOps 基础架构:可追溯性的关键作用

在当今竞争激烈的软件环境中,快速交付强大的应用程序至关重要。尽管如此,在不影响质量的情况下保持速度可能是一项艰巨的任务,这就是 DevOps 中的可追溯性发挥作用的地方。通过提供软件开发生命周期 (SDLC) 的透明视图…

用C++ Qt实现安卓电池充电动效 | 打造工业级电量控件

一、为什么需要自定义电池控件? 在工业控制、车机系统、智能硬件等领域的UI开发中,电池状态显示是高频出现的UI组件。通过实现一个支持颜色渐变、动态充电动画、警戒阈值提示的电池控件,开发者可以系统掌握以下核心能力: Qt绘图…

一批起飞猪名单配图

好久没有使用风口猪选股指标了,今天去玩了一把,发现起飞猪指标显示了好多一批猪票 华曙高科 汉威科技 双林股份 曼恩斯特 长盈精密 江苏雷利 双飞集团 奥飞数据 硅宝科技 水晶光电 长盈精密

机器学习笔记——常用损失函数

大家好,这里是好评笔记,公主号:Goodnote,专栏文章私信限时Free。本笔记介绍机器学习中常见的损失函数和代价函数,各函数的使用场景。 热门专栏 机器学习 机器学习笔记合集 深度学习 深度学习笔记合集 文章目录 热门…

Ubuntu 服务器Llama Factory 搭建DeepSeek-R1微调训练环境

1.首先了解一下什么是LLM微调 LLM 微调指的是在已经预训练好的大型语言模型基础上,使用特定的任务数据或领域数据,通过进一步的训练来调整模型的参数,使其在特定任务或领域上能够表现得更好。简单来说,就是对一个已经具备了丰富语…

环境变量与本地变量

目录 本地变量的创建 环境变量VS本地变量 认识完了环境变量我们来认识一下本地变量。 本地变量的创建 我们如果直接env是看不到本地变量的,因为本地变量和环境变量都具有独立性,环境变量是系统提供的具有全局属性的变量,都存在bash进程的…

智慧农业新生态 | 农业数字化服务平台——让土地生金,让服务无忧

一部手机管农事,从播种到丰收,全链路数字化赋能! 面向农户、农机手、农服商、农资商打造的一站式农业产业互联网平台,打通农资交易、农机调度、农服管理、技术指导全场景闭环,助力乡村振兴提效增收。 三大核心场景&am…

【运维自动化-作业平台】如何创建执行方案和作业模板

蓝鲸智云作业平台,以下简称作业平台或JOB平台作业模板和执行方案:将运维操作场景中涉及到的多个脚本执行或文件分发步骤组合成一个作业模板,这个作业模板尽可能把场景相关的共性逻辑都包含进去,然后再根据实际使用场景衍生出相应的…

广度优先搜索--之重生之我是蒟蒻,从入坟到入坑式讲解

广度优先搜索 1.什么是广度优先搜索? 广度优先搜索(Breadth-First Search,简称BFS)是一种遍历或搜索树和图的算法,也称为宽度优先搜索,BFS算法从图的某个节点开始,依次对其所有相邻节点进行探索和遍历&am…

CSDN文章质量分查询系统【赠python爬虫、提分攻略】

CSDN文章质量分查询系统 https://www.csdn.net/qc 点击链接-----> CSDN文章质量分查询系统 <------点击链接 点击链接-----> https://www.csdn.net/qc <------点击链接 点击链接-----> CSDN文章质量分查询系统 <------点击链接 点击链…

为AI聊天工具添加一个知识系统 之113 详细设计之54 Chance:偶然和适配 之2

本文要点 要点 祖传代码中的”槽“ &#xff08;占位符变量&#xff09; 和 它在实操中的三种槽&#xff08;占据槽&#xff0c;请求槽和填充槽&#xff0c; 实时数据库&#xff08;source&#xff09;中数据(流入 ETL的一个正序流程 行列并发 靶向整形 绑定变量 &#xff09…

微信小程序实现拉卡拉支付

功能需求&#xff1a;拉卡拉支付&#xff08;通过跳转拉卡拉平台进行支付&#xff09;&#xff0c;他人支付&#xff08;通过链接进行平台跳转支付&#xff09; 1.支付操作 //支付 const onCanStartPay async (obj) > {uni.showLoading({mask: true})// 支付接口获取需要传…

Spring框架基本使用(Maven详解)

前言&#xff1a; 当我们创建项目的时候&#xff0c;第一步少不了搭建环境的相关准备工作。 那么如果想让我们的项目做起来方便快捷&#xff0c;应该引入更多的管理工具&#xff0c;帮我们管理。 Maven的出现帮我们大大解决了管理的难题&#xff01;&#xff01; Maven&#xf…

unity学习46:反向动力学IK

目录 1 正向动力学和反向动力学 1.1 正向动力学 1.2 反向动力学 1.3 实现目标 2 实现反向动力 2.1 先定义一个目标 2.2 动画层layer&#xff0c;需要加 IK pass 2.3 增加头部朝向代码 2.3.1 专门的IK方法 OnAnimatorIK(int layerIndex){} 2.3.2 增加朝向代码 2.4 …

力扣hot100——螺旋矩阵 超简单易懂的模拟搜索方法

给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 解法思路&#xff1a; // 模拟螺旋搜索设定四个边界// left right// top |————————————————|// | |// |…