我想要做的是将一组( n )项目拆分为相同大小的组(大小 m 的组,为简单起见,假设没有剩余,即 n 可被 m 整除。多次执行 ,我希望确保没有一对项目在同一组中一起两次。
为了使这一点更加具体,为了构建六个项目A..F
中的两个组,可以用不同的方式对该组进行五次分区:
(A, B)
,(C, D)
,(E, F)
(A, C)
,(B, E)
,(D, F)
(A, D)
,(B, F)
,(C, E)
(A, E)
,(B, D)
,(C, F)
(A, F)
,(B, C)
,(D, E)
同一组项目只能划分为三个一组,而不会重叠:
(A, B, C)
,(D, E, F)
(正如@DavidHammen在下面指出的那样,在这个例子中有不同的方法来制作分区。但是,一旦进行了一次分区,就不会有另一个第二次分割,它将所有项目对分开。这就是很好 - 我的应用程序不需要生成所有可能的方法来全局分区集,一个满足约束的解决方案就可以了)
我现在的问题是:有没有办法有效地做到这一点?是否有技巧加速这些集的生成?
所以,到目前为止,我一直将此视为exact cover问题,并使用backtracking algorithm(DLX的变体)解决此问题。这对于对很有效,但随着组变大,算法必须考虑爆炸的可能性数量,并且处理变得非常难以处理。
我正在寻找的是加快提升的技巧。任何想法都非常受欢迎,特别是(但不限于):
非常欢迎任何想法和建议。 非常感谢你考虑这个!
更新
好的,所以这已经有一段时间了,但我花了很多时间在这上面,并想回到你身边。 @ david-eisenstat通过给我正确的搜索词让我走上正确的道路(非常感谢你!) - 我已经阅读了很多关于社交高尔夫球手问题的文章。
我想在这里分享的最好的资源之一是Markus Triska的工作,他在论文中讨论了几种方法(然后继续提出一个非常好的算法)。如果有人遇到类似的问题,强烈建议这样做!
答案 0 :(得分:8)
此问题的研究名称为Social Golfer Problem。文献具有重要的规模,但有三种主要方法:
本地搜索方法,可以处理不存在多对的情况。
完整的搜索方法,例如缩小到完全封面。根据我的记忆,这里的研究围绕着对称破坏的有效方法,你修复第一行的想法可能是最简单的。
数学结构。当q是一个主要的力量时,q个q组的构造涉及finite affine planes并不太难以实现。除此之外,还有很多一次性的结构。 “组合设计手册”可能是您总结已知内容的最佳选择。
答案 1 :(得分:0)
允许n=m*k
,分区包含m
个k
项组。
x
分区后,每个项目都在一个包含x*(k-1)
个其他项目的组中。创建t-1
分区后,在下一个分区A
中可以选择:
second element : n - (t-1)*(k-1) - 1 items
third element : n - 2*(t-1)*(k-1) - 2 items
fourth element : n - 3*(t-1)*(k-1) - 3 items
...
k'th element : n - (t-1)*(k-1)^2 - (k-1) items
要创建t'th
分区,我们需要:
n - (t-1)*(k-1)^2 - (k-1) > 0
=>
t < (n - k + 1) / ((k-1)^2) + 1
可能的分区数量随组长度的平方而减少。这意味着,没有太多可能的分区: - )
我会采取一些贪婪的方法。存储每个可用项目的项目集,并通过将第一个可用项目添加到组来创建新分区。