我甚至不确定这是否可以在多项式时间内完成。
问题:
给出两个实数数组,
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])
应该比任何其他组合都大。任何线索?
答案 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似乎必须包含正数。