繁体   English   中英

Python - 使用递归计算总可能性

[英]Python - Calculating total possibilities using recursion

我试图找到如何在 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)

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

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

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

经过一番研究,我发现这篇文章与您的问题有关。

正如在那里解释的那样,递归方法会导致大量的计算时间很长,但是......

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

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

  • 但是回想一下 p(i,k) = Σj p(ik,j) = psum(ik,k)

  • 所以 psum(i,k+1) = psum(i,k) + psum(ik,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(ik,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)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM