我很难开始为这个问题布局代码。
我有固定数量的随机数,在这种情况下是8个数字。 R [] = {1,2,3,4,5,6,7,8};
这将被放置在3组数字中,唯一的约束是每组包含最少一个值,并且每个值只能使用一次。 修改:应使用所有8个数字
例如:
R1 [] = {1,4}
R2 [] = {2,8,5,6}
R3 [] = {7,3}
我需要遍历集合R1,R2,R3的所有可能组合。订单并不重要,所以如果上面的例子发生了,我不需要
R1 [] = {4,1}
R2 [] = {2,8,5,6}
R3 [] = {7,3}
NOR
R1 [] = {2,8,5,6}
R2 [] = {7,3}
R3 [] = {1,4}
什么是好方法?
答案 0 :(得分:3)
我面前有Knuth第4卷,分册3,生成所有组合和分区,第7.2.1.5节生成所有集合分区(分册中的第61页) 。
首先,由于George Hutchinson,他详细列出了算法H,字典顺序中的限制增长字符串 。它看起来很简单,但我现在不打算深入研究它。
在下一页的详细说明设置分区的格雷码下,他思考:
但是,假设我们对所有分区不感兴趣;我们可能只想要那些 m 块的。我们可以通过较小的限制增长字符串集合来运行它,但仍然一次改变一个数字吗?
然后他详细说明了由Frank Ruskey提出的解决方案。
简单的解决方案(并且肯定是正确的)是对分区上的算法H过滤进行编码,其中m==3
并且没有任何分区是空集(根据您声明的约束)。我怀疑算法H运行速度非常快,因此过滤成本不会很高。
如果您在8051上实现此功能,则可以从Ruskey算法开始,然后仅对包含空集的分区进行过滤。
如果你在小于8051和毫秒的事情上实现这一点,你可以使用一个独特的元素(三个级别的简单嵌套循环)为三个分区中的每个分区播种,然后通过对剩余的五个分区进行分区来扩充使用Ruskey算法的m==3
元素。您不必过滤任何东西,但您必须跟踪要分区的五个元素。
从一般算法中滤除的好处是你不必验证自己的任何聪明,并且稍后你会改变主意你的约束,而不必修改你的聪明。
我甚至可能会在以后解决问题,但现在一切都是这样。
P.S。对于Java孔雀鱼:我发现在“George Hutchison限制增长字符串”中搜索某个包ca.ubc.cs.kisynski.bell,其中包含实现Hutchison算法的方法growthStrings()的文档。
上找到答案 1 :(得分:1)
可能不是最好的方法,但应该有效。
确定总和为8的三个数字组合的数量:
1,1,6
1,2,5
1,3,4
2,2,4
2,3,3
为了找到上述内容,我开始使用:
6,1,1 then subtracted 1 from six and added it to the next column...
5,2,1 then subtracted 1 from second column and added to next column...
5,1,2 then started again at first column...
4,2,2 carry again from second to third
4,1,3 again from first...
3,2,3 second -> third
3,1,4
知道不到一半是2,必须找到所有组合......但由于列表不长,我们不妨到最后。
现在将每个3的列表从最大到最小排序(反之亦然) 现在将每个3的列表相互排序。 将每个唯一列表复制到唯一列表列表中。 我们现在拥有添加到8的所有组合(我认为五个列表)。
现在考虑上面一组中的列表
6,1,1所有可能的组合都可以通过以下方式找到:
8选6,(因为我们挑选了6个,只有2个可供选择)2选1,1挑1 这可以达到28 * 2 * 1 = 56,值得知道有多少可能性,以便你可以测试。
n选择r(从n个总选项中选择r个元素)
n C r = n! / [(n-r)! r!]
所以现在你有第一个列表的每个组件的迭代总数,它是28 ...
从8中挑选6个项目与创建8个减去2个元素的列表相同,但是哪两个元素?
好吧,如果我们删除了1,2,3,6,6,7,8。让我们考虑所有2个组...从1,2开始,下一个将是1,3 ...所以以下是逐列读取。
12
13 23
14 24 34
15 25 35 45
16 26 36 46 56
17 27 37 47 57 67
18 28 38 48 58 68 78
总结上面的每一列给出了28.(所以这只覆盖了列表中的第一个数字(6,1,1)重复第二个数字(一个)的过程,即“2选择1”所以在上面列表中左边两位数的位置,我们选择两个中的一个,然后在最后我们选择剩下的一个。
我知道这不是一个详细的算法,但我希望你能够开始。
答案 2 :(得分:1)
将问题解决了,您将找到一个直截了当的解决方案。你有8个号码,每个号码都需要分配给一个组;如果至少为每个组分配了一个号码,“解决方案”只是一个解决方案。
琐碎的实现将涉及8个for循环和一些IF(伪代码):
for num1 in [1,2,3]
for num2 in [1,2,3]
for num3 in [1,2,3]
...
if ((num1==1) or (num2==1) or (num3 == 1) ... (num8 == 1)) and ((num1 == 2) or ... or (num8 == 2)) and ((num1 == 3) or ... or (num8 == 3))
Print Solution!
它也可以使用两个数组和几个函数递归地实现。更好更容易调试/遵循(伪代码):
numbers = [1, 2, 3, 4, 5, 6, 7, 8]
positions = [0, 0, 0, 0, 0, 0, 0, 0]
function HandleNumber(i) {
for position in [1,2,3] {
positions[i] = position;
if (i == LastPosition) {
// Check if valid solution (it's valid if we got numbers in all groups)
// and print solution!
}
else HandleNumber(i+1)
}
}
第三个实现将不使用递归和一点回溯。 Pseudocode,再次:
numbers = [1,2,3,4,5,6,7,8]
groups = [0,0,0,0,0,0,0,0]
c_pos = 0 // Current position in Numbers array; We're done when we reach -1
while (cpos != -1) {
if (groups[c_pos] == 3) {
// Back-track
groups[c_pos]=0;
c_pos=c_pos-1
}
else {
// Try the next group
groups[c_pos] = groups[c_pos] + 1
// Advance to next position OR print solution
if (c_pos == LastPostion) {
// Check for valid solution (all groups are used) and print solution!
}
else
c_pos = c_pos + 1
}
}
答案 3 :(得分:0)
以经典方式递归生成子集的所有组合。当您到达剩余元素数等于空子集数量的点时,请仅限制为空子集。
这是一个Python实现:
def combinations(source, n):
def combinations_helper(source, subsets, p=0, nonempty=0):
if p == len(source):
yield subsets[:]
elif len(source) - p == len(subsets) - nonempty:
empty = [subset for subset in subsets if not subset]
for subset in empty:
subset.append(source[p])
for combination in combinations_helper(source, subsets, p+1, nonempty+1):
yield combination
subset.pop()
else:
for subset in subsets:
newfilled = not subset
subset.append(source[p])
for combination in combinations_helper(source, subsets, p+1, nonempty+newfilled):
yield combination
subset.pop()
assert len(source) >= n, "Not enough items"
subsets = [[] for _ in xrange(n)]
for combination in combinations_helper(source, subsets):
yield combination
测试:
>>> for combination in combinations(range(1, 5), 2):
... print ', '.join(map(str, combination))
...
[1, 2, 3], [4]
[1, 2, 4], [3]
[1, 2], [3, 4]
[1, 3, 4], [2]
[1, 3], [2, 4]
[1, 4], [2, 3]
[1], [2, 3, 4]
[2, 3, 4], [1]
[2, 3], [1, 4]
[2, 4], [1, 3]
[2], [1, 3, 4]
[3, 4], [1, 2]
[3], [1, 2, 4]
[4], [1, 2, 3]
>>> len(list(combinations(range(1, 9), 3)))
5796