You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

带执行时间、截止日期与惩罚的作业排序算法求解问询

嘿,这个带惩罚的作业调度问题我太熟了!你现在的困境我完全理解——要在串行执行的前提下,让未按时完成的作业总惩罚最小,其实换个角度想就通了:我们要尽量保住惩罚高的作业,让它们能在截止日期前完成,剩下的惩罚低的就算超时,总损失也最小。下面给你拆解清晰的思路和可运行的代码:

算法核心思路

这个问题用「贪心+最大堆」的组合解法最高效,核心逻辑围绕“优先保高惩罚作业”展开,步骤如下:

  • 排序作业:把所有作业按惩罚从高到低排序;如果惩罚相同,就按执行时间从短到长排序。这么做是为了先把最“赔不起”的作业纳入考虑范围。
  • 用堆维护选中作业:用一个最大堆(快速找到执行时间最长的作业)来跟踪已选中的作业,同时记录这些作业的总执行时间。
  • 动态调整选中集合:遍历排序后的每个作业:
    1. 把当前作业加入堆,总执行时间加上该作业的时长。
    2. 检查总执行时间是否超过当前作业的截止日期:
      • 如果超过了,说明当前选中的作业堆里存在“冗余”——因为我们是按惩罚从高到低选的,堆里的作业惩罚都不低于当前作业,所以移除执行时间最长的那个作业(这样能最大程度减少总执行时间,同时损失的惩罚最小)。
代码示例(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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:30:17