因此,如果我正确理解了您的问题,那么我认为下面的代码(在 Go 中)可以解决。如果您可以假设每个分布的积分相等(这意味着可以将一个转换为另一个),那么只需移动通过你的分布,从左到右,并在每一点计算出需要从右侧移动多少污垢,或者需要从那里向左侧移动多少多余的污垢。在所有情况下,您都可以假设您需要的任何污垢都可以得到,因此暂时有“负面”污垢是可以的。
// Finds out how to move dirt to transform b into a.
// assumes that the integrals over a and b are equal
func earthMover(a, b []int) []int {
r := make([]int, len(a))
for i := 0; i < len(a); i++ {
// if diff is positive it means that there is too much dirt here and it
// must be moved to the right. if it is negative it means some dirt
// needs to be pulled in from the right. In either case dirt can be
// moved over multiple spaces.
diff := b[i] - a[i]
r[i] = diff
b[i] -= diff
if i < len(a) - 1 {
b[i+1] += diff
}
}
return r
}
这是一个例子。负数表示从右侧拉入污垢,正数表示从左侧推到右侧。我认为对于您的指标,您只需将移动数组中的所有数字相加,因此这种情况的解决方案是 5。
target: [ 3 0 1 0 2 6]
source: [ 1 1 5 0 1 4]
move: [-2 -1 3 3 2 0]
现在我看到了,如果这确实是您想要的,那么您实际上是在寻找分布的加权平均值或质心(污垢)的差异。例如:
0 1 2 3 4 5
target: [ 3 0 1 0 2 6]
weighted: 0 +0 +2 +0 +8+30 = 40
source: [ 1 1 5 0 1 4]
weighted: 0 +1+10 +0 +4+20 = 35
如您所见,目标的质心减去源的质心就是我们之前得到的数字,40 - 35 = 5。