存在包含N个整数的集合S,每个整数具有值1 <= X <= 10 ^ 6。问题是将集合S划分为k个分区。分区的值是其中存在的元素的总和。分区将以这样的方式完成,集合S的总值在k个分区之间公平分配。 fair 的数学含义也需要定义(例如,目标可以是最小化分区值与集合S的平均值的标准偏差(即,和(S) / k))的
e.g。 S = {10,15,12,13,30,5},k = 3
一个好的分区是{30},{10,15},{12,13,5}
错误的分区是{30,5},{10,15},{12,13}
第一个问题是在数学上表达一个分区的条件要好于另一个分区。 第二个问题是如何解决问题。问题是NP-Hard。有任何启发式吗?
在我试图解决的问题中,N&lt; =(k * logX)^ 2,K从2变为7。
=============================================== ===================================
根据其他相关的SO问题,评估分布有两个合理的功能:
a)使用最大值最小化分区的值。
再想一想,这不是一个好的指标。考虑一组{100,40,40}被分成三个子集。该指标不区分以下两个分布,即使一个明显优于另一个。
分发1:{100},{40},{40}和分发2:{100},{40,40},{}
b)最小化给定分区中任何两个值的差异的最大值,即最小化max | A-B |任何A,B
答案 0 :(得分:6)
我认为一个好的指标是:
let the result set be s1,s2,...,sk
let MAX be max{sum(si) for each i}
f({s1,...,sk}) = Sigma(MAX-sum(si)) for each i)
好处:完美的分配将永远为0!
缺点:如果没有perferct解决方案,最好的结果将不会产生0。
这个问题的贪心启发式将是:
sorted<-sort(S) (let's say sorted[0] is the highest)
s1=s2=...=sk= {}
for each x in sorted:
s <- find_min() (*)
s.add(x)
其中find_min()产生s,使得每个si的sum(s)&lt; = sum(si)。
这个解决方案将产生f(上面定义的度量),使得f(sol) <= (k-1)*max{S}
(从这里它是这个边界的证据):
声明:对于每个子集s,MAX- sum(s) <= max{S}
证明 - 通过归纳:在每一步,对于临时解决方案都是如此。
在每一步中,让MAX在迭代开始时(加法之前)为max {sum(si)}!
base: the set of subsets at start is {},{},.. MAX=sum(si)=0 for each si.
step: assume the assumption is true for iteration i, we'll show it is also true for iteration i+1:
let s be the set that x was added to, then MAX-sum(s) <= max{S} (induction assumption).
if sum(s) + x <= MAX: we are done, MAX was not changed.
else: we sorted the elements at start, so x <= max{S}, and thus if s was chosen
(sum(si) >= sum(s) for each si) and sum(s) + x > MAX then: for each si, sum(si) + x >=
sum(s) + x, so sum(s)+x - sum(si) <= x <= max{S}. since sum(s)+x will be the MAX next
iteration, we are done.
因为对于每个集合MAX-sum(si) <= max{S}
(显然,对于最大集合,MAX-sum(si)=0
),在整体Sigma(MAX-sum(si)) <= (k-1)*max{S}
,正如所承诺的那样。
编辑: 我有一些空余时间,所以我编写了由我和@Akhil建议的两种启发式算法,两个指标,首先,两个结果都是结论性的(根据Wilcoxon的成对测试)但是哪个更好是由您选择的指标定义的,令人惊讶的是,试图最小化f()(@ Akhil`s)的算法对于同样的f得分较低,但对于第二个指标得分较高。
答案 1 :(得分:1)
一种启发式方法是尽可能均匀地在袋子中散布较大的重量,留下足够小的重量,现在你留下一个具有大量自由度的子问题。如有必要,重复进入子子问题。这种启发式假设您的分布不是太几何,例如{1000} and {100, 10, 1}
,并略微假设您的惩罚函数将惩罚零指派或非常大的异常值。
例如:
distributeFairly(numbers, bins):
distributeFairlySubproblem(numbers, bins):
n = len(numbers)
numElementsToDefer = min(-n//3,20*k) # modify as appropriate, e.g. to avoid len(toPlace)<len(toDefer)
toDefer = numbers[-numElementsToDefer:]
toPlace = numbers[:-numElementsToDefer]
newBins = shoveThemIn(toPlace, copy(bins))
return distributeFairlySubproblem(toDefer, newBins)
initialGuess = distributeFairlySubproblem(sorted(numbers,reverse=True), [[]]*k)
return anneal(initialGuess)
答案 2 :(得分:1)
让度量最小化max(sum(si) - sum(sj))其中si和sj是集合S的结果分区中的任意两个子集。
假设我们有一个分布D,我们需要在分布D中包含另一个元素x。将它添加到子集s中,以使上面的度量最小化。
无法证明任何界限,但直觉说它会给出最佳的近似值?有资格证明自己的人吗?