如何找到解决所有 N 个问题所需的最短时间?

Posted

技术标签:

【中文标题】如何找到解决所有 N 个问题所需的最短时间?【英文标题】:How to find the minimum time required to solve all N problems? 【发布时间】:2015-05-22 17:33:13 【问题描述】:

我试图解决这个问题,但即使过了几个小时我也无法解决 完全理解问题。我什至无法上来 使用任何蛮力技术。这就是问题:

有 N 个成员和 N 个问题,每个成员必须准确解决 1 个问题。团队中只允许一名成员阅读 在任何人开始解决之前的问题陈述。

请注意,并不是每个人一开始都阅读过这些问题。所以,要解决 成员需要知道某个队友的陈述的问题 已经认识他们了。知道问题一次后,会员才有资格 向其他队友解释(一次一位队友)。你可以 假设解释(1或N个问题)总是需要D 分钟。在解释过程中,两名涉事成员都不会 可以做任何其他事情。

问题具有不同的难度级别。你可以假设它 将花费 Ti 分钟来解决第 i 个问题,无论哪个 会员解决了。

给定一个团队的数据,他们最少可能需要多少时间 能解决所有问题吗?

输入

N  D
2 100

T=[1 2]

Output

102

允许成员 1 在开始时间之前知道问题。他开始 比赛开始时向成员 2 解释问题。解释结束于 第 100 分钟。然后他们俩立即开始解决 并行的问题。成员 1 在第 101 分钟解决了第一个问题 成员 2 在第 102 分钟解决了第 2 个问题。

解码这类问题并解决它的最佳方法是什么?

【问题讨论】:

N 可以有多大?我们可以选择谁在开始时间之前了解所有问题,还是总是成员 1? @IVlad N≤3×10^3 。是的,我们可以选择任何成员..不一定是 1.. 问题陈述没有多大意义。鉴于您陈述的条件,解决所有问题总是需要D + N 分钟。现在,如果成员可以在向他解释问题后立即开始解决问题(即他不必等待所有问题都得到解释),那么您就有了要解决的问题。 @JimMischel 但是一个成员只能解决一个问题,一旦他解决了问题,他就必须坐 Idle 。所以我们需要确保在最短的时间内解决所有问题。 【参考方案1】:

这让我想起了Huffman coding。

我不确定以下方法是否最佳,但在实践中它可能会给出一个很好的答案。

    选择最简单的两个问题 T0 和 T1,并将它们替换为由时间 D+max(T0,T1) 组成的单个问题。 重复直到剩下一个问题

如果将问题存储在二进制堆中,则可以在 O(logN) 中找到两个最简单的问题,因此总体而言这是 O(NlogN)。

示例

假设我们有 1,3,4,6 和 D=2。

我们首先将 1 和 3 组合成 2+max(1,3)=5。新列表是 4,5,6

然后我们将 4 和 5 结合起来,使 2+max(4,5)=7。新列表是 6,7。

然后我们将 6 和 7 组合成 2+max(6,7)=9。

这表示以下过程。

t=0 A shares with B
t=2 A starts problem 6, B shares with C
t=4 B starts problem 4, C shares with D
t=6 C starts problem 3, D starts problem 1
t=7 D finishes
t=8 A finishes, B finishes
t=9 C finishes

【讨论】:

其实我到现在也没找到反例,你有吗?如果事实证明这是最优的,那就太好了。 我没有反例,我只是没有勇气尝试证明...... 那么我们是否需要对时间进行排序并使用贪心策略求解,即先求解最高执行时间,然后再求解第二高,等等?? 不完全是,它更像是一种贪心策略,最后解决两个最短的任务(其中一个任务要么是原始问题之一,要么是已经合并的问题的组合) @PeterdeRivaz 为什么我们不能对时间 T 进行排序以获得两个最简单的问题。这需要 O(n^2lohn) 时间,因为我们必须在每次合并两个最简单的问题后进行排序。【参考方案2】:

团队的每个成员(阅读问题的人除外) 必须听到问题。也就是说,问题必须被告知N - 1 次。 对于N = 2,这可以在D 分钟内完成, 对于2 < N <= 42D 分钟, 对于4 < N <= 83D 分钟等。

如果N 不是 2 的精确幂,那么有些人必须说完 问题至少比其他人早D 分钟。 提早完成的人可以继续工作 最难的问题,把更容易的问题留给后来完成的问题。

如果某些问题需要时间Ti > DN 都不是精确的 2 的幂,也不小于 2 的精确幂,您可能想要 有人比D 分钟前停止告诉问题更多 最后的问题讲完了。

如果有些问题需要时间Ti > 2D那么你可能需要考虑 让一些人停止讲述问题并开始研究真正的问题 即使N 是 2 的精确幂,也能尽快解决难题。

由于解决一个问题是每个成员的关键路径, 但讲述在多个成员的关键路径中, 任何人在完成之前解决问题都是没有意义的 他们将要解决的所有问题。 每D分钟后知道问题的人数 讲问题的人数增加。 讲问题的人数增加了讲问题的人数 正在讲述问题(即,刚刚学会了 问题)减去当时开始解决问题的人数。

一个好的“蛮力”方法可能是对问题进行排序 按难度;然后找出最后一个人听到的时间 如果在此之前没有人开始处理这些问题; 找出最后一个人何时结束; 然后尝试提前D 分钟或2D 分钟开始问题, 或3D 分钟等,但永远不要启动较短的运行 在一个运行时间较长的问题之前出现问题。

【讨论】:

“团队的每个成员......必须听到问题”---不。第一个成员实际解决所有问题而不是描述可能会更快。 @Petr - 不,问题陈述说每个成员必须解决一个问题。 哦,抱歉,没注意到这个 Peter de Rivaz 的解决方案在大多数情况下看起来像是一个很好的启发式方法,我试图找到一个反例但没有成功。我的猜测是这将是最好的答案。【参考方案3】:

问题陈述对解释部分有些模棱两可。根据语句的解释方式,可能有以下解决方案:

如果你假设你可以在 D 分钟内解释 N 个问题,那么解释一个问题需要 N/D 分钟。让我们称之为Te,表示“解释时间”。而解决问题i 的时间是Ti,我们知道它等于i 分钟。

所以在比赛开始时,成员 1(知道所有问题)向成员 2 解释问题 N。这需要 Te 分钟。然后成员 2 开始处理问题 N(需要 N 分钟解决),成员 1 开始向成员 3 解释问题 N-1。这种情况一直持续到成员 1 向成员 N 解释问题 2。此时,成员 N 开始处理问题 2,成员 1 开始处理问题 1。

假设有 4 个问题、4 个团队成员和D=8。所以Te=2

Time    Description
 0      Member 1 begins explaining Problem 4 to Member 2
 2      Member 2 begins working on Problem 4
        Member 1 begins explaining Problem 3 to Member 3
 4      Member 3 begins working on Problem 3
        Member 1 begins explaining Problem 2 to Member 4
 6      Member 2 completes problem 4
        Member 4 begins working on Problem 2
        Member 1 begins working on Problem 1
 7      Member 3 completes Problem 3
        Member 1 completes Problem 1
 8      Member 4 completes Problem 2

无论DN 的值如何,这似乎都是最佳解决方案:安排它以使解决时间最长的问题尽早开始。

我怀疑问题陈述是用其他语言给出的问题的英文翻译,或者可能是对最初用英语编写并翻译成其他语言的内容的重新翻译。因为如果那是最初的问题陈述,那么写它的人应该被禁止再写问题。

【讨论】:

【参考方案4】:

完成任何一项任务所需的时间长度似乎是C * D + T, where C is a positive integer less than N 的形式,并且必须考虑所有N-1 的提前期。假设我们犯了一个错误,而最佳解决方案实际上应该有一个任务加上更长的交货时间——所以有些C * D + Tj < C * D + Ti, where Ti < Tj,这是不可能的。

因此,对对的总和进行一次迭代(假设输入已排序):

solution = maximum (T2 + (n-1) * D, T3 + (n-2) * D...D + Tn)

【讨论】:

以上是关于如何找到解决所有 N 个问题所需的最短时间?的主要内容,如果未能解决你的问题,请参考以下文章

信息熵

UVA-1632 Alibaba (区间DP+滚动数组)

二分,求直线上覆盖所有点的最短时间

19新生赛 蚂蚁问题

《挑战程序竞赛》1.6.2 Ants poj1852

codeforces 730 J Bottles