我这里有一个场景。让我用一个小例子来解释。
我有10支钢笔,我必须把它交给3个人。那些人的比例如6:6:1表示如果我给人C一笔,我必须给A人和B人6-6笔。
我试图通过使用我在下面描述的简单计算来解决它。
PerPersonPen = (TotalCountofPens * PerPersonRatio)/(SumofAllPersonsRatio)
Person A =(Int) (10*6)/13 = 4
Person B = (Int) (10*6)/13 = 4
Person C = (Int) (10*1)/13 = 0
在这里,人物C将获得0笔,但它不应该发生。我希望那个人A& B正在获得4笔,这是正确的。但是人C也应该得到1支笔。
这种情况发生在任何人与其他人相比有1个比率计数的情况下。
有人可以帮我解决这个问题吗?或者我怎样才能实现它?
答案 0 :(得分:4)
一种简单的方法是保持每个人应该获得多少笔的数量。然后,只要它们是钢笔分发,你给一个应该得到最多笔的人。
以下是您的示例:
60/13 ,60 / 13,10 / 13 - > 1 ,0,0
47/13, 60/13 ,10/13 - > 1, 1 ,0
47/13 ,47 / 13,10 / 13 - > 2 ,1,0
34/13, 47/13 ,10/13 - > 2, 2 ,0
34/13 ,34 / 13,10 / 13 - > 3 ,2,0
21/13, 34/13 ,10/13 - > 3, 3 ,0
21/13 ,21 / 13,10 / 13 - > 4 ,3,0
8/13, 21/13 ,10/13 - > 4, 4 ,0
8 / 13,8 / 13, 10/13 - > 4,4, 1
8/13 ,8/13,-3 / 13 - > 5 ,4,1
<强>更新强> 如果你想确保每个人在可能的情况下至少收到一支笔,那么首先给每个人一支笔,优先考虑那些需要最多笔的人,以防你没有足够的笔给每个人。然后按上述步骤进行。
答案 1 :(得分:1)
Laurent G在评论部分How to round numbers fairly
中提供了一个非常有用的数学堆栈交换链接这篇文章暗示了以下算法:
x_i
比率x_i = her share/sum of shares
C_min = numberOfPens
和C_max
设置得足够大,以便sum_i (floor(x_i*C_max)) > numberOfPens
(C_max = numberOfPens + 1/(min x_i)
可以正常工作)C_min
和C_max
之间进行二分搜索,直到找到C
sum_i (floor(x_i*C)) = numberOfPens
然而,当存在关系时(例如,在两个比率值为6/13的情况下),这可能不起作用。但你可以做的是添加一个非常小的随机噪音(你加上或减去不到原始比率之间存在的最小非零差距的一半)与你的比率来打破关系并得到一般的结果,这将是“几乎公平“。
编辑:我注意到我最初选择C_max
是错误的,所以我将其修改为有效的东西。不过我觉得还有改进的余地。通过在C_max
中增加k
,也可以找到最初的2^k numberOfPens
,直到满足标准(sum_i(floor(x_i*C_max)) > numberOfPens
)。
答案 2 :(得分:0)
在查看您的示例时,很明显每个人都应该至少获得您计算的结果。 只有一些人会得到更多。
我建议以下算法:
Math.Ceiling(assigned value)
,其中k是期望值 - 我们在步骤2中计算的总和。在我们的示例中为10-8。(int) (assigned value)
。答案 3 :(得分:-1)
像
这样的东西int_weights = [6, 6, 1]
total_weights = sum(int_weights)
to_share = 10
still_to_share = to_share
left_weight_total = total_weights
shares = []
for weight in int_weights:
s = int(0.5 + (float(still_to_share) * weight / left_weight_total))
still_left -= s
left_weight_total -= weight
shares.append(s)
这给出了相当但不绝对的公平性(这不能通过关系实现,参见我在问题评论中发布的链接)
shares
[5,4,1]
sum(shares)
0
如果你想达到公平关系,最好的结果是[4, 4, 2]
(或[5, 5, 0]
[:auto_censored_but_not_totally:] ;-)?)你可以通过排序和考虑到达以前的分配。直到我得到一个好的论据才能成为那个挑剔的人,我会继续使用上面所示的解决方案。