具有两个数组的最大子集和

时间:2011-11-11 20:07:26

标签: arrays algorithm math subset-sum

我甚至不确定这是否可以在多项式时间内完成。

问题:

  

给出两个实数数组,

A = (a[1], a[2], ..., a[n]), 
B = (b[1], b[2], ..., b[n]),  (b[j] > 0, j = 1, 2, ..., n)
     

和一个数字k,找到A'的子集A (A' = (a[i(1)], a[i(2)], ..., a[i(k)])),其中包含k个确切的元素,以便最大化(sum a[i(j)])/(sum b[i(j)]),其中<登记/> j = 1, 2, ..., k

例如,如果结果是k == 3{a[1], a[5], a[7]},那么

(a[1] + a[5] + a[7])/(b[1] + b[5] + b[7])

应该比任何其他组合都大。任何线索?

2 个答案:

答案 0 :(得分:3)

假设B的条目是肯定的(听起来好像这个特殊情况可能对您有用),则会有O(n^2 log n)算法。

让我们首先解决为特定t决定是否存在解决方案的问题

(sum a[i(j)])/(sum b[i(j)]) >= t.

清除分母,这个条件相当于

sum (a[i(j)] - t*b[i(j)]) >= 0.

我们所要做的就是选择k的{​​{1}}最大值。

现在,为了解决a[i(j)] - t*b[i(j)]未知时的问题,我们使用动力学算法。将t视为时间变量;我们感兴趣的是一维物理系统的演化,t粒子具有初始位置n和速度A。每个粒子最多一次穿过彼此的粒子,因此事件的数量为-B。在交叉点之间,O(n^2)的最优值线性变化,因为sum (a[i(j)] - t*b[i(j)])的相同子集是最佳的。

答案 1 :(得分:2)

如果B可以包含负数,则这是NP-Hard。

由于这个问题的NP难度:

  

给定k和数组B,是否存在B的大小为k的子集,其总和为零。

在这种情况下,A变得无关紧要。

当然,从您的评论看来,B似乎必须包含正数。