【问题标题】:Can the minimum time to schedule tasks be found without brute force?可以在没有蛮力的情况下找到安排任务的最短时间吗?
【发布时间】:2020-03-06 04:03:45
【问题描述】:

如果我有一个整数列表,表示完成一项任务所需的时间,并且我有 x 个工作人员只能处理一项任务,直到完成所需的时间结束,我能找到它的最短时间吗可能会采取最好的情况吗?我不需要构成这个最短完成时间的确切排列,只需要时间。

例如,为了简单起见,如果我有一个列表 [2, 4, 6] 并且我有 2 个工作人员,那么如果我从 2 和 4 开始,那么当 2 完成时 6 将开始,这意味着需要 8 秒完成所有任务。但是,如果我从 6 和 2 开始,那么当 2 完成时,4 将与 6 同时开始和完成,因此如果按此顺序完成任务,则只需 6 秒。

有没有比n 知道只需要6 秒的方法!还是蛮力复杂性保证它是可能的最短时间?感谢您提前提供的任何帮助,如果我遗漏了任何细节或您感到困惑,请随时提出问题!

编辑:请帮助:(

编辑 2:有可能吗?有人知道吗?

【问题讨论】:

  • 我认为在这种情况下,找到“在最佳情况下可能花费的最短时间”需要与确定任务执行顺序相同的工作量(即确定排列)。这个问题我没有想太多,但它让我想起了Knapsack Problem。但是,找到最小下限是一个更简单的问题,我认为这是您要寻找的术语,而不是“最佳情况”。
  • 同意,我想要最短时间的原因是,而不是迭代到 n!为了找到最佳排列,我可以迭代直到找到最短时间然后中断,所以我只是想知道是否有一些公式或其他东西可以确定小于 n 的最短时间!欢呼告诉我背包问题很有趣@Dai
  • 顺便说一句,您可能还想查看en.wikipedia.org/wiki/Hungarian_algorithm,因为我认为您的问题是调度问题的一个实例,其中所有工作人员对每个任务都有相同的成本 - 在这种情况下,您可以找到在最多O(n^4) 提供的时间内(其中n == workers * tasks)最好的解决方案(无需寻找界限)优于O(n!)
  • 您正在寻找任务集合的 makespan。有很多先前的工作需要审查。
  • @HighPerformanceMark 你知道我在哪里可以找到这项工作来审查吗?我已经做了一些研究,感谢你告诉我 makepan 这个术语有很大帮助,但几乎我能找到的每一个算法都涉及一些规定,比如 x 任务必须在 y 之前完成,而我的程序没有这样的规定所以他们的算法对我没有多大帮助。感谢您的帮助!

标签: list math optimization scheduled-tasks code-complexity


【解决方案1】:

在单个worker的情况下,实际所需的总时间与所有任务时间的总和相同。

jobs = [ 2, 4, 6, etc... ]
time_required = SUM( jobs )

如果有两个工人,那么给定特定的工作顺序,所需的总时间可以通过首先将每个任务的所需时间分配给具有当前最低总和的工人来确定,然后获得与每个工人相关的最高总和:

define type worker  = vector<time_t>
define type workers = min_priority_queue<worker> using worker.sum() # so the current worker.sum() (the sum of `time_t` values in `vector<time_t>`) is the priority-queue key.
define type task    = int

jobs = [ 2, 4, 6, etc... ]

# Use two workers:
workers.add( new worker )
workers.add( new worker )

# Iterate once through each job:
foreach( task t in jobs ) {

    minWorker = workers.getMinWorker() # priority queue "find-min" operation
    minWorker.add( t )
}

# Determine which worker will work the longest time:
time_required = workers.getMaxWorker().sum() # priority queue "find-max" operation

因为这是一个实际的解决方案,所以 time_required 是一个存在于上限和下限之间的点样本 - 这并不是您所追求的,而是因为它可以在 @987654325 中计算@time 这是一个很好的起点。

然后可以将上述算法推广到任意数量的工作人员,只需将它们添加到优先级队列 - 因为基于堆的优先级队列的 find-min 操作是 O(1) 我相信这个算法在 O(n) 时间运行n 是工作数量,与工人数量无关。 (我可能对精确的运行时复杂度有误)。

至于在少于O(n!) 时间的时间内计算边界...这很棘手(至少对我来说,因为我上次破解my copy of CLRS 已经有几年了)。

对于任何个作业顺序的xworkers 的最小下界就是作业集中的最大单个值。

xworkers 对于任何个工作顺序的最大上限可能是最大的工作100 * (1/x) % 的总和(所以给定 2 个工作人员最大的 50% 工作的总和,对于 3 个工人,它是最大的 33% 工作的总和,对于 4 个工人,它是 25%,等等)。这将要求您首先对集合进行排序(如果使用 Quicksort,则采用 O(n log n))。

jobs = [ 2, 4, 6, etc... ]

worker_count = 2

jobs.sortDescending() # O(n log n)

# if there's 50 jobs and 2 workers, then take the first 25 jobs and sum them...
# ...that's an upper_bound for the time required to complete all tasks by 2 workers, as it assumes that 1 unlucky worker will get all of the longest tasks

upper_bound = jobs.take( jobs.count / worker_count ).sum() 

【讨论】:

  • 很好的解决方案,找到前半部分任务的总和(在 2 个工人的情况下)并不总是最小值,但不幸的是,在 [8,2,2, 2] 最好的解决方案是 8 秒,但最大数字的前半部分的总和是 10。任何排序都无济于事,除非我能事先知道可能的最短时间,否则将无法知道何时休息出去。感谢您的帮助!
  • @mizuprogrammer 我的帖子说找到降序排序值的前半部分的总和将产生一个上限,而不是下限。
  • 啊,我很抱歉你是对的,我看错了,你的解决方案是正确的,但对于下限,它并不总是集合中的最大数字,因为我不能假设我总是有和我做任务一样多的工人。感谢所有的帮助! :) @Dai
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-08-27
  • 1970-01-01
  • 2023-03-09
  • 2021-07-31
  • 2015-06-15
  • 2019-03-22
  • 2020-11-25
相关资源
最近更新 更多