将数字分组,以使其总和的差异最小

时间:2017-03-21 13:34:38

标签: excel excel-vba excel-formula vba

我找到了一些类似的线程,但我相信我的有点独特。这很难写,所以请耐心等待。

我有一个10个帐户的压力,每个帐户都有一个不能拆分的静态数字。我有3名员工需要尽可能分开这些帐户。他们无法共享帐户。

例如:

(A)lpha    = 15    
(B)eta     = 30    
(C)harlie  = 22    
(D)elta    = 19    
(E)cho     = 28    
(F)ranklin = 3    
(G)roto    = 7    
(H)enry    = 28    
(I)ndia    = 38    
(J)uliet   = 48

总和是= 238.在完美的世界中,2个人会得到79,而一个人会得到80个。但是,请记住我们不能拆分帐户,所以我们需要一起添加帐户以便尽可能接近尽可能地传播。

我需要一个公式,因为这种情况经常发生,需要一些时间才能解决这个问题。我相信这最好用辅助列执行。

我最接近的是:

FHJ  = 79
ABCG = 74
DEI  = 85

但是由于这种情况一再发生并且可能发生在更多帐户上,我需要一些可以反复使用的东西。

2 个答案:

答案 0 :(得分:3)

另一个不太复杂但近似的解决方案是

  1. 将您的帐户从最高编号分类到最低编号。
  2. 开始将数字分为3组(A,B,C)
    • 从3个最高数字开始(.nopaddingPanel { padding: 0 !important; margin: 0 !important; } 48|J38|I)排序到A,B和C组
    • 下一个最高编号(30|B)将转到总和最低(C)
    • 的组
    • 下一个最高号码(28|E)进入总和最低(B)
    • 的组
    • 等......
  3. 你应该最终得到这个:

    enter image description here

    这与您的手动解决方案不同,但更接近。如果你看到差异:

    • 上述解决方案:28|H
    • 您的手动解决方案:81 - 77 = 4

    此算法是近似值,它不会总是找到最佳解决方案但如果最低和最高数字之间的差异不是太大,那么结果非常接近最佳解决方案。

答案 1 :(得分:2)

这被称为partition problem。您可以尝试从Wikipedia页面实现伪多项式时间算法。您必须将其修改为3个分区而不是2个。

INPUT:  A list of integers S
OUTPUT: True if S can be partitioned into two subsets that have equal sum
1 function find_partition(S):
2     n ← |S|
3     K ← sum(S)
4     P ← empty boolean table of size (floor(K/2)+ 1) by (n + 1)
5     initialize top row (P(0,x)) of P to True
6     initialize leftmost column (P(x, 0)) of P, except for P(0, 0) to False
7     for i from 1 to floor(K/2)
8         for j from 1 to n
9             if (i-S[j-1]) >= 0
10               P(i, j) ← P(i, j-1) or P(i-S[j-1], j-1)
11            else
12               P(i, j) ← P(i, j-1)
13    return P(floor(K/2), n)