我对作业(非抢占式)调度算法的算法复杂性有疑问,特别是用于获得1 || sum(Uj)问题的最优解(仅一台机器),其中Uj是单一惩罚(即:如果作业在截止日期前终止,则等于0,如果作业延迟终止则等于1)。
我需要尽量减少单一罚款的总和(即:晚期工作的总和)。给出了作业处理时间及其截止日期,并且没有释放时间(因此,所有作业在时间t = 0时同步释放)。 算法的工作原理如下:
1-根据最早到期日计算所有工作
2-确定第一个迟到的工作Jj。如果没有迟到的工作,请转到第4步。
3-确定Jj与其前任之间最大的处理时间作业。删除该作业并返回步骤2,考虑没有删除作业的新序列
4-最佳序列由下式给出:当前序列[后跟]在步骤3中以任何顺序删除的作业子集。
我被要求计算这个算法的最坏情况O(...)复杂度,在一般和良好的实现情况下(所以,我必须尝试猜测复杂性“无实现”),给出所有算法步骤。)
我认为第1步需要O(nlogn),因为(使用QuickSort或MergeSort)只需要订购。
但是,那么,步骤2-3-4怎么样?如果我们试图在C / C ++中实现这一点,那么最终的复杂性可能是O(n ^ 2)是否正确?或者是O(n * logn),这要归功于EDD“优化”后续搜索?什么可以证明其复杂性?
提前多多感谢。
答案 0 :(得分:2)
在我看来,整个算法可以在*---------------------------*
| ApprID | Date | Status |
|--------|--------|---------|
| 1 | xxxxxx | 1 |
| 2 | xxxxxx | 2 |
| 3 | xxxxxx | 3 |
| 4 | xxxxxx | 2 |
*---------------------------*
时间内完成。基本思路是分摊去除前辈的成本。每次我们移除前任广告时,我们都会向O(n log n)
付费,最多会有O(log n)
次移除。
这是具体细节。在步骤1之后,您只需要对作业执行一次传递,因为从序列中删除作业只能使作业更快完成。每当您考虑序列中的作业时,您会反复删除其最大的前任,直到它按时完成。请注意,“删除最大的前任”操作的总数最多为n
,因为每个作业最多只会删除一次。 [注意:我认为这里需要一些注意,因为“前任”应该是一个包容性的概念。也就是说,在考虑特定作业j时,如果j大于任何先前作业,则应删除j并继续下一个作业。]
如何有效地实施“删除最大的前任”操作?您可以通过按作业大小维护(从左到右的作业)对前任的排序来实现此目的。这种排序可以用例如二进制搜索树来实现,该搜索树允许n
中的插入和删除。每次开始考虑工作时,都要将其插入树中,支付O(log n)
。删除最大的前任只是删除树中最大的作业。
之前我们注意到,最多会有O(log n)
个删除,相当于树中最多n
个删除。因此,我们为删除支付了总费用n
。我们还为插入支付了总费用O(n log n)
(每个作业只需插入一次)。排序所有数据的预处理步骤为O(n log n)
,因此所有步骤的总费用为O(n log n)
。
这是一些伪代码:
O(n log n)
我遗漏的唯一细节是如何检查工作是否按时完成。但这非常简单,因为您可以通过在从树中插入和删除作业时添加和减去计数器来跟踪“当前完成时间”。