找到最小化总和的排列

时间:2014-12-07 00:43:41

标签: algorithm data-structures dynamic-programming

我有一个元素数组[(A1, B1), ..., (An, Bn)](所有都是正浮点数和Bi< = 1)我需要找到最小化和A1 + B1 * A2 + B1 * B2 * A3 + ... + B1 * ... B(n-1) * An的这种排列。

当然我可以尝试所有这些并选择给出最小总和的那个(这将在O(n!)中给出正确的结果)。

我尝试将总和更改为A1 + B1 * (A2 + B2 * (A3 + B3 * (... + B(n-1) * An))并尝试使用贪婪算法,该算法在每个步骤上抓取最大的Ai元素(这不会产生正确的结果)。

现在,当我查看最新的等式时,在我看来,在这里我看到了最佳子结构A(n - 1) + B(n - 1) * An,因此我必须使用动态编程,但我无法找出正确的方向。有什么想法吗?

1 个答案:

答案 0 :(得分:3)

我认为这可以在O(N log(N))中解决。

通过交换相邻元素对可以获得任何排列;这就是为什么冒泡排序有效的原因。我们来看看交换条目(A[i], B[i])(A[i+1], B[i+1])的效果。我们想知道在哪种情况下进行这种交换是个好主意。这仅对ii+1条款有效,所有其他条款保持不变。此外,在交换之前和之后,这两个术语都有B[1]*B[2]*...*B[i-1]因子,我们现在可以调用CC是一个正数。

在互换之前,我们正在处理的两个术语是C*A[i] + C*B[i]*A[i+1],之后它们是C*A[i+1] + C*B[i+1]*A[i]。如果两者之间的差异为正,则这是一种改进:

C*(A[i] + B[i]*A[i+1] - A[i+1] - B[i+1]*A[i]) > 0

由于C是肯定的,我们可以忽略该因素并仅查看AB。我们得到

A[i] - B[i+1]*A[i] > A[i+1] - B[i]*A[i+1]

或等效

(1 - B[i+1])*A[i] > (1 - B[i])*A[i+1]

这两个表达都是非负的;如果B[i]B[i+1]中的一个为1,那么包含'one minus that variable'的术语为零(因此,如果B[i]为1,我们应该交换,但如果B[i+1]则不应该交换是一个);如果两个变量都是1,则两个项都为零。我们现在假设两者都不等于一;然后我们可以进一步重写以获得

A[i]/(1 - B[i]) > A[i+1]/(1 - B[i+1])

因此,我们应该为这两个术语计算这个表达式D[i] := A[i]/(1 - B[i]),如果左边的一个大于右边,则交换它们。我们可以将此扩展到B中的一个或两个是{1}}的情况,在这种情况下将D[i]定义为无限大。

好的,让我们回顾一下 - 我们发现了什么?如果有一对ii+1其中D[i] > D[i+1],我们应该交换这两个条目。这意味着我们无法通过交换来改善结果的唯一情况是,当我们重新排序这些对时,D[i]值的顺序递增 - 也就是说B[i] = 1的所有情况都来了last(回想一下,这对应于D[i]无限大),否则以D[i]值递增。我们可以通过对D[i]值进行排序来实现这一点。快速检查上面的步骤表明,具有相等D[i]值的对的顺序不会影响最终值。

计算所有D[i]值可以在单个线性时间传递中完成。可以使用O(N log(N))算法进行排序(我们需要交换相邻元素的东西仅作为参数/证明,以表明这是最佳解决方案,而不是实现的一部分)。