带执行时间、截止日期与惩罚的作业排序算法求解问询
嘿,这个带惩罚的作业调度问题我太熟了!你现在的困境我完全理解——要在串行执行的前提下,让未按时完成的作业总惩罚最小,其实换个角度想就通了:我们要尽量保住惩罚高的作业,让它们能在截止日期前完成,剩下的惩罚低的就算超时,总损失也最小。下面给你拆解清晰的思路和可运行的代码:
算法核心思路
这个问题用「贪心+最大堆」的组合解法最高效,核心逻辑围绕“优先保高惩罚作业”展开,步骤如下:
- 排序作业:把所有作业按惩罚从高到低排序;如果惩罚相同,就按执行时间从短到长排序。这么做是为了先把最“赔不起”的作业纳入考虑范围。
- 用堆维护选中作业:用一个最大堆(快速找到执行时间最长的作业)来跟踪已选中的作业,同时记录这些作业的总执行时间。
- 动态调整选中集合:遍历排序后的每个作业:
- 把当前作业加入堆,总执行时间加上该作业的时长。
- 检查总执行时间是否超过当前作业的截止日期:
- 如果超过了,说明当前选中的作业堆里存在“冗余”——因为我们是按惩罚从高到低选的,堆里的作业惩罚都不低于当前作业,所以移除执行时间最长的那个作业(这样能最大程度减少总执行时间,同时损失的惩罚最小)。
代码示例(Python)
Python的heapq模块默认是最小堆,所以我们用存负数的方式模拟最大堆,代码里加了详细注释,方便你理解:
import heapq def schedule_jobs(jobs): # 作业格式:(执行时间, 截止日期, 惩罚) # 第一步:按惩罚降序排序,惩罚相同则按执行时间升序,优先保留高惩罚、短时长的作业 jobs.sort(key=lambda x: (-x[2], x[0])) max_heap = [] # 存储执行时间的负数,模拟最大堆(heapq默认最小堆) total_exec_time = 0 selected_jobs = [] for time, deadline, penalty in jobs: # 将当前作业加入堆和选中列表 heapq.heappush(max_heap, -time) total_exec_time += time selected_jobs.append((time, deadline, penalty)) # 如果总执行时间超过当前作业的截止日期,必须移除一个作业 # 移除执行时间最长的,这样总时间减少最多,且损失的惩罚最小(因为堆里作业惩罚都>=当前) if total_exec_time > deadline: longest_time = -heapq.heappop(max_heap) total_exec_time -= longest_time # 从选中列表中移除对应作业(这里假设同一执行时间的作业不影响,取第一个匹配的) for idx, job in enumerate(selected_jobs): if job[0] == longest_time: selected_jobs.pop(idx) break # 计算最小总惩罚:所有作业惩罚总和 - 选中作业的惩罚总和 total_penalty_all = sum(job[2] for job in jobs) total_penalty_selected = sum(job[2] for job in selected_jobs) min_total_penalty = total_penalty_all - total_penalty_selected # 生成可行的调度顺序:按截止日期升序排序,确保每个作业都能在截止日期前完成 selected_jobs.sort(key=lambda x: x[1]) return min_total_penalty, selected_jobs # 测试用例 if __name__ == "__main__": # 示例作业:(执行时间, 截止日期, 惩罚) test_jobs = [ (3, 4, 20), (1, 2, 10), (2, 4, 30), (2, 3, 40) ] min_penalty, optimal_schedule = schedule_jobs(test_jobs) print(f"最小总惩罚: {min_penalty}") print("最优调度顺序(按执行先后):") for seq_num, job in enumerate(optimal_schedule, 1): print(f"第{seq_num}个作业:执行时间{job[0]}, 截止日期{job[1]}, 惩罚{job[2]}")
结果说明
运行测试用例后,你会得到最小总惩罚为20(对应第一个作业超时),最优调度顺序是按截止日期排序的两个作业:先执行时长1、截止2的作业(完成时间1≤2),再执行时长2、截止4的作业(完成时间3≤4),完全满足时间约束。
内容的提问来源于stack exchange,提问作者JohnnyK
相关产品推荐
相关产品推荐

