【问题标题】:Dynamic programming script for the best way to sum numbers动态编程脚本,用于求和数字的最佳方法
【发布时间】:2021-04-04 17:22:46
【问题描述】:

我正在尝试学习一些动态编程的基本知识,但我遇到了以下问题:

给定一个整数 sum 和一个正整数列表 numbers,返回由属于 numbers 且总和为 sum 的最小数量组成的列表。

希望这很清楚,我给你举三个例子:

如果sum = 10numbers = (2, 3, 5) 应该返回[5, 5]; 如果sum = 0numbers = (2, 3, 5) 应该返回[]; 如果sum = 10numbers = (3) 应该返回False

def bestsum(sum, numbers, memo={}):
    if sum == 0:
        return []
    elif sum < 0:
        return False
    else:
        if sum not in memo:
            shortest_combination = False
            for number in numbers:
                remainder = sum - number
                combination = bestsum(remainder, numbers)
                if combination != False:
                    combination.append(number)
                    if shortest_combination == False or len(combination) < len(shortest_combination):
                        shortest_combination = combination
            memo[sum] = shortest_combination
        return memo[sum]

我没有将memo 作为我对bestsum 的递归调用的输入,因为它与我之前做过的其他动态程序一起使用。但是,即使我添加它,脚本也不起作用,即使我没有明确地这样做,它也会更新memo。添加copy.copy 或实际插入我的memo 作为输入无济于事。也许问题在于,当我调用不同的函数以及可能递归地调用其他函数时,我仍然想念变量在我的记忆中是如何生活的。

【问题讨论】:

标签: python dynamic-programming


【解决方案1】:

除了 cmets 中列出的问题(即可变默认参数,使用内置函数的名称作为变量名)之外,如果您要传递 memo 参数(编辑:实际上想一想,无论如何都会发生这种情况..)。

对于所提到的所有问题,只需极少的更改,最快的解决方案可能会让您得到这个

def bestsum(s, numbers, memo=None):
    if memo is None:
        memo = {}
    if s == 0:
        return []
    elif s < 0:
        return False
    else:
        if s not in memo:
            shortest_combination = False
            for number in numbers:
                remainder = s - number
                combination = bestsum(remainder, numbers, memo)
                if combination != False:
                    combination = combination.copy()
                    combination.append(number)
                    if shortest_combination == False or len(combination) < len(shortest_combination):
                        shortest_combination = combination
            memo[s] = shortest_combination
        return memo[s]

(这并不是说这是最优雅的处理方式,更多的是直接修复您的代码)

至于我会怎么做:

def bestsum(s, numbers):
    sums = {0:[]}
    while(s not in sums and len(sums)>0):
        sums = {k+n:l+[n] for k,l in sums.items() for n in numbers if k+n<=s}
    if(s not in sums):
        return None
    else:
        return sums[s]

【讨论】:

    【解决方案2】:

    我对代码库进行了一些更改并添加了一些 cmets,但我保留了大部分:

    def bestsum(sum, numbers, memo={}):
        if sum == 0:
            return []
        elif sum < 0:
            return False
        else:
            if sum not in memo:
                for number in numbers:
                    remainder = sum - number
                    shortest_combination = bestsum(remainder, numbers, memo)
                    if shortest_combination != False:
                        # Good news! We found a valid path from `sum` to the end
                        if (
                            sum not in memo
                            or len(memo[sum]) > len(shortest_combination) + 1
                        ):
                            # Either there's no entry in memo for `sum` yet
                            # Or we've found a better subpath than the current one
                            currently_best_combination = shortest_combination.copy()
                            currently_best_combination.insert(0, number)
                            memo[sum] = currently_best_combination
                if sum in memo:
                    # Return value if we've found a valid path 
                    return memo[sum]
                else:
                    # Return false if not
                    return False
            else:
                # If sum is already in `memo`, it's already the optimal way
                return memo[sum]
    
    numbers = [2, 3, 5]
    print(bestsum(10, numbers))
    # [5, 5]
    
    numbers = [2, 3, 5]
    print(bestsum(0, numbers))
    # []
    
    numbers = [3]
    print(bestsum(10, numbers))
    # False
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-04-22
      • 1970-01-01
      • 1970-01-01
      • 2015-02-14
      • 2011-02-07
      • 1970-01-01
      • 2012-05-25
      相关资源
      最近更新 更多