【问题标题】:Python - Calculating total possibilities using recursionPython - 使用递归计算总可能性
【发布时间】:2020-07-04 02:20:46
【问题描述】:

我正在尝试找出如何将 90 个苹果放入 90 个盒子中的全部可能性。任何数量的苹果都可以放在一个盒子里(0 到 90 个苹果),但所有的苹果都必须放在盒子里。我使用了递归,但完成计算花费了太多时间。我只能用少量的苹果和盒子来测试我的代码。谁能帮我降低代码的时间复杂度?提前致谢。

import math

boxes = 3
apples = 3

def possibilities(apples, boxes):
    if apples == 0:
        return 1
    if boxes == 0:
        return 0
    start_point = 0 if boxes > 1 else math.floor(apples/boxes)

    p = 0
    for n in range(start_point, apples+1):
        p += possibilities(apples-n, boxes-1)
    return p

t = possibilities(apples,boxes)
print(t)

【问题讨论】:

  • 更多与数学相关的问题可能会在本网站的数学版本中询问。如果是我,我会做 9 个盒子,然后将结果乘以 10,但我的数学不是那么好。
  • 这可以用二项式系数解决,它内置在一些py模块中:stackoverflow.com/questions/26560726/…
  • @Guy_g23 我不认为二项式系数可以解决这个问题,但如果你能证明它可以,我很乐意改变主意。
  • @JacquesGaudin 这是一个组合问题,因为任何正数和离散数量的苹果都可以放在一个盒子里。检查这个答案:math.stackexchange.com/a/58756
  • @Guy_g23 好的,我认为这取决于这些盒子是否可识别。 en.wikipedia.org/wiki/Stars_and_bars_%28combinatorics%29

标签: python performance recursion statistics


【解决方案1】:

在我看来,问题在于找到最大 90 个元素的总和等于 90 的排序列表的数量。

有一个与此非常接近的概念,我们称之为数字的分区。

比如4的分区是[4], [3, 1], [2, 2], [2, 1, 1], [1, 1, 1, 1]

经过一番研究,我发现this article 与您的问题相关。

正如那里所解释的,递归方法会导致对大数进行非常长的计算,但是...

一种更有效的方法是通过称为dynamic programming 的方法。这里我们计算一个函数 psum(n,k),它是具有 k 或更小的最大分量的 n 分区的总数。在任何给定阶段,我们将计算某个固定 k 的 psum(1,k)、psum(2,k)、psum(3,k)、...、psum(n,k) 的值。给定这个 n 个值的向量,我们计算 k+1 的值如下:

  • 对于任何值 i,psum(i,k+1) = psum(i,k) + p(i,k)

  • 但请记住 p(i,k) = Σj p(i-k,j) = psum(i-k,k)

  • 所以 psum(i,k+1) = psum(i,k) + psum(i-k,k)

因此,稍加注意,我们可以重用值向量,并以滚动值计算 psum(i,k) 的值,以获得连续更大的 k 值。最后,我们有一个向量,其值为 psum(i,n)。值 psum(n,n) 是期望值 p(n)。作为一个额外的好处,我们看到我们同时计算了 p(1), p(2), ..., p(n) 的值。

基本上,如果您将中间值保留在一个列表中并使用文章中介绍的重复出现,

psum(i,k+1) = psum(i,k) + psum(i-k,k)

您可以使用以下功能:

def partitionp(n):
    partpsum = [1] * (n + 1)
    for i in range(2, n + 1):
        for j in range(i, n + 1):
            partpsum[j] += partpsum[j - i]
    return partpsum[n]

在外部 for 循环的每次迭代中,列表partpsum 包含所有值 psum(1,k), psum(2,k), psum(3,k), ..., psum(n, k)。迭代结束,只需要返回psum(n,n)即可。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-16
    • 1970-01-01
    • 1970-01-01
    • 2013-11-26
    • 1970-01-01
    • 2015-03-10
    • 1970-01-01
    • 2020-05-25
    相关资源
    最近更新 更多