如何分发整数列表尽可能接近平衡?

时间:2017-03-17 23:09:40

标签: python algorithm

如何平衡一组物品?通过平衡,4个变量中的每个变量与任何其他变量的差异不应超过+1。

每个数字必须保持完整,因为它们代表要转移的1个物理项目。

Input a=1, b=2, c=3, d=10 
Output a=4, b=4, c=4, d=4
Ouput:
    Move 3 from d to a
    Move 2 from d to b
    Move 1 from d to c

Input a=1, b=2, c=0, d=0
Ouput a=1, b=1, c=1, d=0
Output:
    Move 1 from b to c

Input a=1, b=0, c=0, d=0
Output a=1, b=0, c=0, d=0
Output:
    Move None

Input a=0, b=1, c=0, d=1
Output a=0, b=1, c=0, d=1
Output:
    Move None

2 个答案:

答案 0 :(得分:2)

不,它不是一组if / else语句。将值放入列表中,而不是单独的变量。取均值,截断为整数。复制意味着在另一个相同长度的列表中。你现在有类似

的东西
vals = [1, 3, 4, 10]
mean = [4, 4, 4, 4]

请注意,您还剩2件物品。你需要分发这些。 在均值列表中,将1添加到平均值之上的任何元素,直到剩余剩余或元素为止。你现在有了

vals = [1, 3, 4, 10]
mean = [4, 4, 4, 5]

在这种情况下,你还剩下1个。将其添加到任何其他元素:

vals = [1, 3, 4, 10]
mean = [4, 5, 4, 5]

现在,比较列表,一次一个元素,并报告所需的动作是不成比例的。这为您提供了最少量的移动项目,以获得所需的分布。

这会让你前进吗?

对OP评论的回应

首先,您的帖子要求余额,而不是所需的一系列转移。接下来,我不知道 琐事的地方。任何低于"意味着" array是收件人;更多的是捐赠者。您永远不会让产品移动多次:只需将转移限制为可用金额和所需金额中的较小者。

考虑一个简单但非平凡的案例:

vals = [1, 2, 10, 1, 6]
mean = [4, 4, 4, 4, 4]
diff = [-3, -2, 6, -3, 2]

您可以按任何顺序识别动作;为简单起见,我们将在两组中从右到左。是的,有一个简单的解决方案,如果E给B提供2个超额,而C给A和D提供3个,但问题并没有要求最少的货物,只有有效的物品数量。

A 有1项,但需要4:从 C 中取出它们,第一个元素有多余的,有6个额外元素。

vals = [4, 2, 7, 1, 6]
mean = [4, 4, 4, 4, 4]
diff = [0 -2, 3, -3, 2]

B 还需要2件商品,也可以从 C 获得:

vals = [4, 4, 5, 1, 6]
mean = [4, 4, 4, 4, 4]
diff = [0, 0, 1, -3, 2]

D 还需要3个,但 C 只剩下一个:接受它。

vals = [4, 4, 4, 2, 6]
mean = [4, 4, 4, 4, 4]
diff = [0, 0, 0, -2, 2]

...最后,最后一次转移是显而易见的。

会让你再次移动吗?

答案 1 :(得分:1)

这是一个开始。

要获得平衡值,您可以将平均值分配给每个变量。将有一些休息(sum modulo len),只需将它分配给第一个变量:

def distribute(*values):
    low = min(values)
    high = max(values)
    if high - low <= 1:
        print 'already balanced'
        return list(values)
    s = sum(values)
    n = len(values)
    avg = s // n
    result = [avg] * n
    for i in range(s % n):
        result[i] += 1
    return result

print(distribute(1, 2, 0, 0))
# [1, 1, 1, 0]

现在你只需要逻辑来判断从一个变量到另一个变量应该有多少值(例如&#34;将1从b移到c&#34;)。