拆分书堆的可能性

时间:2016-01-17 15:31:12

标签: python algorithm combinatorics

我在Python中遇到了以下问题。问题更像是数学特定于Python特定。

我有很多N本书作为Stack。还有一些P堆栈要拆分。 我正在寻找分裂这个堆栈的可能性,避免重复和空堆栈。

那么让我们说我的筹码是4本书高,分成2个筹码的可能性有多大?

分裂的可能性是:

(1,3)
(2,2)

还有(3,1)的可能性,但由于(1,3)已经在我的输出中,我不希望(3,1)也在那里。

另一个例子:

  

5本书,3个堆栈

(3,1,1)
(2,2,1)

(1,1,3)(2,1,2)等解决方案在我的输出中,因为它们是多余的。

我正在寻找一种 EFFICIENT 方式来计算堆栈的元组。 我正在使用最大400的起始堆栈,这个堆栈可以拆分成另一个堆栈,也可以拆分,等等。

是否已有参考资料涵盖此问题?

我认为用组合术语来解决很容易,但问题在于,我对自己的可能性感兴趣而不仅仅是可能性的数量!

这里有什么帮助吗?

欢呼

1 个答案:

答案 0 :(得分:3)

消除重复:

您可以通过对每个组合进行第一次排列来完成此操作。

换句话说,前面有最小的堆栈。 例如{1,2,3}, {1,3,2} {2,1,3} {2,3,1} < /秒>, {3,1,2} {3,2,1}

效率:

您可能希望通过递归执行此操作,因此在每个步骤中您都知道堆栈的可能大小至少前一个

的大小

您知道所有后续的stackSizes必须至少是当前大小。所以最大尺寸是剩下的书籍数量除以剩余的书籍数量(floor)。

E.g。剩下3本书的10本书。 floor(10/3) = 3。哪个是正确的,因为此时留下的最大组合是{3,3,4}

因此,这将阻止您进入失败的组合。

代码

import math

def bookStack(cur, min, booksLeft, sizes):
    if len(sizes) == (cur+1):
        sizes[cur] = booksLeft
        print(sizes)
        return;
    max = math.floor(booksLeft / (len(sizes)-cur))+1;
    for take in range(min,max):
        sizes[cur] = take
        bookStack(cur+1, take, booksLeft-take, sizes)

对于超过3个堆栈的5本书,请使用以下方法调用:

bookStack(0,1,5,[0]*3)

Run it here

备注:虽然你想要所有独特的组合,但这仍然是一个快速增长的功能,只适用于少量的堆栈。或者当堆栈数量与书籍数量几乎相等时。你会注意到的。