如何为类似“背包”的问题创建贪婪算法?

问题描述

假设有n个球,每个球的权重最多为1。我们可以假设将这些球的权重放在数组W [1..n]中,其中0

我要为此设计一种有效的贪婪算法。我认为一个明显的选择(选择最大的第一和最小的第二)是不正确的。但是,如果我先选择最大的可用球,然后再选择第二个最大的球,那该怎么办?我认为这是正确的,但是我不确定如何证明这一点。这样做会产生普通的O(n ^ 2)算法。

这似乎是背包问题的一种变体,但是贪婪算法并不是最优的。

解决方法

贪婪算法的常用证明模板是通过对k进行归纳,证明对于所有k≥0的算法,其前k个选择可以扩展为最优解。事实证明,您的两个想法都是正确的,每个贪婪算法都会将剩余的最大的球与(如果可能的话)任何与之匹配的球反复放入一个盒子中。

归纳法的基本情况k = 0是微不足道的。对于此步骤,请考虑与前k-1个框的贪婪解一致的最优解。设B为不在前k-1个盒子中的最重的球。贪婪包B中的B包。考虑可能性。

  • 如果#k框出现在最佳解中,则后者满足归纳要求的条件。

  • 如果贪婪解决方案本身在一个盒子中有B,则B不适合任何剩余的球,因此最优解决方案本身也有B,并且前k个决策都同意。

  • 如果贪婪的另一个球有B,但是最优值只有B,那么我们可以通过将另一个球移到B的盒子来修改最优解。这种新的解决方案也是最佳的,并且满足归纳条件。

  • 如果贪婪和最优具有不同球的B,那么我们可以在最优解中交换这些球以使其与贪婪解对齐。我们知道这是可能的,因为另一个盒子中的球不能大于B,因为可能大于B的k-1在两种解决方案中的包装方式相同。

您的第二个解决方案可以使用平衡的二进制搜索树在O(n log n)时间内实现。