Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python中递归函数的问题_Python_Python 3.x - Fatal编程技术网

python中递归函数的问题

python中递归函数的问题,python,python-3.x,Python,Python 3.x,我有一个递归定义这个函数的问题。我的目标是让函数返回给定n的最大收入n(以米为单位)这是布的数量。h列表是销售n米长地毯的利润。例如,h[2]=5是制作2米长地毯的利润,为了简单起见,是5美元,h[0]=0,因为没有布料,也没有产品生产。所以h列表就是不同长度地毯的市场价值。如果我有n米的布料,我希望函数返回最大利润。价格仅针对高达4米的地毯定义,因此为什么h列表就是这样。例如,n=2的递归计算出一块2米大的地毯的价值,并将利润与两块1米的地毯进行比较,依此类推 递归大致表述为: 收入(0)=

我有一个递归定义这个函数的问题。我的目标是让函数返回给定
n
的最大收入<代码>n(以米为单位)这是布的数量。
h
列表是销售
n
米长地毯的利润。例如,
h[2]=5
是制作2米长地毯的利润,为了简单起见,是5美元,
h[0]=0
,因为没有布料,也没有产品生产。所以
h
列表就是不同长度地毯的市场价值。如果我有
n
米的布料,我希望函数返回最大利润。价格仅针对高达4米的地毯定义,因此为什么
h
列表就是这样。例如,
n=2
的递归计算出一块2米大的地毯的价值,并将利润与两块1米的地毯进行比较,依此类推

递归大致表述为:

  • 收入(0)=0

  • income(n)=max(h[i]+income(n-i))
    对于
    1您试图解决的问题是无界的一个版本。与其试图最大化你能装进一个包的价值,不如尝试最大化你能用你的布做的地毯的价值。你关心的不是物品的重量,而是地毯上用了多少布。但结果是一样的。在任何情况下,对于任意输入来说,这是一个很难有效解决的问题,但是对于较小的
    n
    值,您可以非常轻松地强制执行它

    您正确地确定了您的递归将永远持续(或者直到递归限制),因为您没有编写基本情况。实际上比这更糟糕,因为第一个递归是
    i
    等于
    0
    ,它再次调用函数,调用的
    n
    与您已经尝试求解的
    n
    完全相同(因为
    n-i
    n
    i==0
    时)

    i
    为零时,您确实不希望递归,因为您根本不会缩小问题的范围。最简单的方法可能只是修改您的
    范围
    ,从
    1开始
    i
    ,然后从那里开始增加。您还需要一些逻辑来防止循环超过索引4,因为对于更长的长度,列表中没有更多的值

    def income(n):
        if n == 0:         # base case
            return 0
        h = [0,2,5,6,9]
        return max(h[i]+income(n-i) for i in range(1, min(n+1, len(h))))  # recursive case
    
    除了为
    n==0
    添加基本情况并修复
    范围之外,我还用执行递归的生成器表达式替换了循环。这是必要的,因为
    max
    需要几个参数(它相互比较),或者一个iterable参数(比较谁的值)。您只传递了一个值,这不起作用

    上面的版本适用于较小的
    n
    值,最大值约为15。但是,要想达到更高的值,需要花费越来越长的时间,因为递归变得非常深入和广泛,最终需要反复计算很多值。这就是我说背包问题很难的意思

    一个可以大大加快速度的技巧是,在第一次计算出结果时缓存每个计算的结果,如果以后需要,使用缓存的值

    _cache = {0: 0}   # the cache is pre-seeded to handle our base case of n=0
    def income(n):
        if n not in _cache:
            h = [0,2,5,6,9]
            _cache[n] = max(h[i]+income(n-i) for i in range(1, min(n+1, len(h))))
        return _cache[n]
    
    我还要进一步指出,对于您的特定
    h
    列表,看起来最好是尽可能多地制作2米长的地毯,如果您从一个奇数
    n
    开始,则最多可以制作一块1米长的地毯来用完最后一米的布料。因此,如果您愿意为示例中非常具体的问题硬编码此最佳解决方案,您可以跳过递归,只需执行以下操作:

    def income(n):
       return n//2 * 5 + n%2 * 2
    

    您的无限递归与列表中的第一个值有关,您总是可以做无限多的免费事情,而这些事情不会给您带来任何利润。也许你应该跳过这个案例,因为什么都不做对你没有任何好处。这看起来是无界的一个版本,很难有效地解决,但对于小案例来说,暴力也不太难。如果现在问题更清楚,我就编辑了这个问题。你永远不会停止递归,因为你永远不会使用
    income(0)=0
    这一事实。每个递归函数应该做的第一件事是检查递归终止条件。另外,你的老师所说的第二个条件是
    max(h[i]+income(n-i)for i in range(1,n+1))
    ;阅读有关列表理解和生成器表达式的内容来理解这一点。感谢您的输入,我已经添加了我提出的解决方案。请随意评论这是否合理。我还添加了我的缓存版本,但我不确定它是否正常工作。
    def income(n):
        if n == 0:         # base case
            return 0
        h = [0,2,5,6,9]
        return max(h[i]+income(n-i) for i in range(1, min(n+1, len(h))))  # recursive case
    
    _cache = {0: 0}   # the cache is pre-seeded to handle our base case of n=0
    def income(n):
        if n not in _cache:
            h = [0,2,5,6,9]
            _cache[n] = max(h[i]+income(n-i) for i in range(1, min(n+1, len(h))))
        return _cache[n]
    
    def income(n):
       return n//2 * 5 + n%2 * 2