工时受限的作业调度问题:贪心算法失效后的优化方案咨询
问题本质与标准贪心失效原因
这是典型的0-1背包问题:每个工作选项只能选一次,总工时上限是背包容量,工资是物品价值。标准贪心算法(按单位工时工资从高到低排序选择)失效的核心原因是——它只适用于可分割的分数背包,但这里的工作选项是不可分割的:你不能只做一半5小时的工作来拿对应比例的工资。
拿你的测试用例来说:
- 7小时70块的时薪约为10元/小时,是单个选项里最高的,但选它之后剩下3小时只能选1小时1块的选项,总工资71;
- 而两个5小时69块的选项,总工时刚好10小时,总工资138,远高于前者。贪心的局部最优选法完全忽略了这种更优的全局组合。
无需暴力解法:动态规划是最优方案
暴力枚举所有子集的时间复杂度是O(2^n),n是工作选项数量,当n超过20就会变得极慢。动态规划能在O(n*C)的时间复杂度内解决问题(n是选项数,C是最大工时,这里是10),效率高且能保证最优解。
动态规划实现步骤
- 定义状态:用
dp[i]表示总工时不超过i小时时,能赚到的最高工资。 - 初始化:
dp[0] = 0,其余dp元素初始为0(因为工时为0时工资为0,其他初始状态还没选任何工作)。 - 状态转移:遍历每个工作选项(工资
w,时长t),然后从后往前遍历工时(从10到t),更新:
从后往前遍历是为了避免重复选择同一个工作选项(保证每个选项只被选一次)。dp[j] = max(dp[j], dp[j - t] + w) - 获取结果:
dp[10]就是单日能赚到的最大工资。
针对测试用例的计算过程
测试用例:工资数组[70,69,69,1],时长数组[7,5,5,1],最大工时10。
- 初始
dp = [0,0,0,0,0,0,0,0,0,0,0] - 处理第一个选项(70元,7小时):
从7到10遍历,更新后dp[7~10]变为70; - 处理第二个选项(69元,5小时):
从5到10遍历,dp[5]变为69,dp[10]更新为max(70, dp[5]+69)=138; - 处理第三个选项(69元,5小时):
遍历后dp[10]保持138(已是最优); - 处理第四个选项(1元,1小时):
遍历后不会改变dp[10]的结果。
最终dp[10] = 138,是正确的最优解。
关于修改贪心算法的可能性
很难通过简单调整标准贪心来保证得到最优解。贪心的核心是局部最优选择,而0-1背包的最优解依赖全局组合。如果只是需要近似解,可以尝试一些启发式贪心(比如同时考虑单位时薪和剩余容量的适配性),但这类方法无法确保100%找到最优解。如果必须得到准确的最大工资,动态规划是远优于暴力解法的选择。
内容的提问来源于stack exchange,提问作者Dnyanesh Shinde
相关产品推荐
相关产品推荐

