我有一个元素数组[(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
,因此我必须使用动态编程,但我无法找出正确的方向。有什么想法吗?
答案 0 :(得分:3)
我认为这可以在O(N log(N))
中解决。
通过交换相邻元素对可以获得任何排列;这就是为什么冒泡排序有效的原因。我们来看看交换条目(A[i], B[i])
和(A[i+1], B[i+1])
的效果。我们想知道在哪种情况下进行这种交换是个好主意。这仅对i
和i+1
条款有效,所有其他条款保持不变。此外,在交换之前和之后,这两个术语都有B[1]*B[2]*...*B[i-1]
因子,我们现在可以调用C
。 C
是一个正数。
在互换之前,我们正在处理的两个术语是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
是肯定的,我们可以忽略该因素并仅查看A
和B
。我们得到
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]
定义为无限大。
好的,让我们回顾一下 - 我们发现了什么?如果有一对i
,i+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))
算法进行排序(我们需要交换相邻元素的东西仅作为参数/证明,以表明这是最佳解决方案,而不是实现的一部分)。