这是一个有趣的问题。我将使用您的示例将数字 1..10 分成三组来说明我的答案。该解决方案将适用于任何一组数字和任何数量的组。当然,当数字集的大小很大时,您可能无法使用蛮力方法。话虽如此,大型数字集也可以用类似的方式处理,但稍后会详细介绍。
假设我们在集合中有 M 个连续数字,表示为 (1..M),我们希望将它们分成 N 个组。
首先要确定的是您将比较每个组的总和的值。这只是一组数字的总和除以组数 N。
在示例中 sumOf(1..M) = 55 和 N = 3,因此 55/3 = 18.33 是每个组应求和的值。您希望最小化组和与 18.33 之间的差异
作为另一个例子,如果你想将数字 1..20 分成两组,那么你需要最小化组和之间的差异,并且 sumOf(1..20) = 210 除以 2 组 = 210/2 = 105。
下一步是找到所有可能的组。这是另一个有趣的问题,考虑到 proups 包含连续数字的限制,组组合的总数并不像您预期的那么多。
寻找组合是一个递归问题,很容易计算出一个通用方程。
让我们从一个简单的案例开始。集合中有多少个 10 个数字的组合 (1..10)。好吧,只有一组,数字 (1..10)
现在,10 个数字中有多少 2 个组的组合。答案是 M-1 或 10-1 = 9,即
(1),(2..10)
(1..2) (3..10)
(1..3) (4..10)
(1..4) (5..10)
(1..5) (6..10)
(1..6) (7..10)
(1..7) (8..10)
(1..8) (9..10)
(1..9) (10)
所以一组大小为 M 的组有 M-1 个组合。这是递归的基础。
这 10 个数字中有多少个 3 组的组合。
嗯,第一组将是以下之一
(1),(1..2),(1..3) ,(1..4) ,(1..5),(1..6) ,(1..7) ,(1..8)
将其中任何一个作为第一组,让我们计算出剩余数字中有多少 2 个组的组合。
让三个中的第一组 = (1)。我们还剩下九个数字,并且知道这些数字可以构成 9-1 = 8 个不同的 2 组组合
让三个中的第一组 = (1..5)。我们还剩下五个数字,它们可以组成 5-1 = 4 个不同的 2 个数字组。
所以,我们总共会有
(1) -> 8 combinations
(1..2) -> 7 combinations
(1..3) -> 6 combinations
(1..4) -> 5 combinations
(1..5) -> 4 combinations
(1..6) -> 3 combinations
(1..7) -> 2 combinations
(1..8) -> 1 combinations
给出 SumOf(1..8) ,或者一般来说 (sum(1..M-2),组的组合。SumOf(1..8) = 8*9/2 = 36
所以 10 个数字中有 3 个组的 36 种组合,每个组包含连续的数字。
顺便说一句,对于 100 个数字中的 3 个组,您有 sumOf(1..98) = 98*99/2 = 4851 个组组合,因此随着 M 的增加,您将获得更多组合,并且作为 M 的某个值蛮力方法可能是不可能的。
上述方法可用于设计一个简单的递归算法,以获取集合 (1..M) 中的所有组组合。
此外,可以为一组 M 个数中的任意数量 N 个组制定一个简单的方程。例如,如果您移动到 10 个数字中的 4 个组,那么您会遇到第一组是 (1..3) 的情况,然后在剩余的 7 个数字中找到 3 个组的组合。将有 sum(1..M-2) = sum(1..5)..etc。
不管怎样,回到问题上来。您拥有组的所有组合,因此您可以遍历组并计算每个组合的 SAD,然后选择最小化 SAD 的组合。
当组合的数量非常多并且您无法查看每个组合时,您可以尝试引导以随机选择组或某种进化算法方法,从随机选择的组合数量开始,然后随机选择将数字从一组转移到另一组,并保留 SAD 最低的那些。继续此步骤,直到您看到 SAD 没有进一步改善。
或者您可以按照@Robert King 的建议进行操作,从一个组合开始,然后通过将数字从一组移动到另一组来改进它。