Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/307.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_Algorithm_Dynamic Programming - Fatal编程技术网

Python 动态规划-使用一组整数计算和的方法的数量

Python 动态规划-使用一组整数计算和的方法的数量,python,algorithm,dynamic-programming,Python,Algorithm,Dynamic Programming,我问了这个问题 不太明白那里的答案, 我写了两种方法来解决一个问题: 使用数字N(允许重复)找出可以达到总和S的方法的数量 和=4,数=1,2,3答案是1111,221122,31,131212212212212 在一种方法中我使用备忘录,而在另一种方法中我不使用。不知怎的,在我的机器上,记忆版本比非记忆版本运行得慢 这两种解决方案都有效 备忘录版本: def find_denomination_combinations(amount, denominations): memo =

我问了这个问题

不太明白那里的答案,

我写了两种方法来解决一个问题:

使用数字N(允许重复)找出可以达到总和S的方法的数量

和=4,数=1,2,3答案是1111,221122,31,131212212212212

在一种方法中我使用备忘录,而在另一种方法中我不使用。不知怎的,在我的机器上,记忆版本比非记忆版本运行得慢

这两种解决方案都有效

备忘录版本:

def find_denomination_combinations(amount, denominations):
    memo = {}

    def calculate_combinations(max_amt):
        return_list = list()

        for denomination in denominations:
            new_sum = max_amt - denomination
            if new_sum == 0:
                return_list.append([max_amt])
                return return_list
            elif new_sum < 0:
                return [[]]
            else:
                if new_sum in memo:
                    combi_list = memo[new_sum]
                else:
                    combi_list = calculate_combinations(new_sum)
                for combination in combi_list:
                    if new_sum in memo and combination[:] not in memo[new_sum]:
                        memo[new_sum].append(combination[:])
                    else:
                        memo[new_sum] = []
                        memo[new_sum].append(combination[:])
                    combination.append(denomination)
                    return_list.append(combination)
        return return_list

    result = calculate_combinations(amount)
    return result
def查找面额组合(金额、面额):
备忘录={}
def计算组合(最大金额):
return_list=list()
对于面额中的面额:
新金额=最大金额-面额
如果new_sum==0:
return\u list.append([max\u amt])
返回列表
elif new_sum<0:
返回[]]
其他:
如果备忘录中有新金额:
组合列表=备忘录[新金额]
其他:
组合列表=计算组合(新组合)
对于组合列表中的组合:
如果备忘录中的新金额和组合[:]不在备忘录中[新金额]:
备注[new_sum].追加(组合[:])
其他:
备忘录[新金额]=[]
备注[new_sum].追加(组合[:])
组合。追加(面额)
return\u list.append(组合)
返回列表
结果=计算组合(金额)
返回结果
非记忆版本

def find_denomination_combinations_nmemo(amount, denominations):

    def calculate_combinations(max_amt):
        return_list = list()

        for denomination in denominations:
            new_sum = max_amt - denomination
            if new_sum == 0:
                return_list.append([max_amt])
                return return_list
            elif new_sum < 0:
                return [[]]
            else:
                combi_list = calculate_combinations(new_sum)
                for combination in combi_list:
                    combination.append(denomination)
                    return_list.append(combination)
        return return_list

    result = calculate_combinations(amount)
    return result
def find_面额_组合_nmimo(金额、面额):
def计算组合(最大金额):
return_list=list()
对于面额中的面额:
新金额=最大金额-面额
如果new_sum==0:
return\u list.append([max\u amt])
返回列表
elif new_sum<0:
返回[]]
其他:
组合列表=计算组合(新组合)
对于组合列表中的组合:
组合。追加(面额)
return\u list.append(组合)
返回列表
结果=计算组合(金额)
返回结果
我的算法是:

[T(sum-D)],其中D属于给定的整数集

如果输入和=16,整数集=[1,2,3]


非备忘录版本运行时间为0.3秒,备忘录版本运行时间为5秒,我认为备忘录版本速度较慢,因为它使用复杂的代码更新最外层的
else
块中的备忘录记录。它可以简单得多:

if new_sum in memo:
    combi_list = memo[new_sum]
else:
    combi_list = memo[new_sum] = calculate_combinations(new_sum)
for combination in combi_list:
    return_list.append(combination + [denomination])
这是非常快的。使用此修复程序,在大多数情况下,记忆版本应该比未记忆的代码快

不过,还有其他问题。如果您的
面额
列表未按递增顺序排序,或者面额值之间存在间隙,则会得到错误的结果。基本上,任何可能导致
elif
案例被命中的情况都会给出错误的结果

以下是针对循环的
主体的一个版本,用于纠正这些问题:

new_sum = max_amt - denomination
if new_sum == 0:
    return_list.append([max_amt]) # don't return here, to allow unsorted denominations!
elif new_sum > 0:
    if new_sum in memo:
        combi_list = memo[new_sum]
    else:
        combi_list = memo[new_sum] = calculate_combinations(new_sum)
    for combination in combi_list:
        return_list.append(combination + [denomination])
# do nothing for new_amt < 0

这稍微慢一点,可能是因为额外的函数调用,但代码要简单得多,没有
elif
else
案例

非常感谢!现在看起来干净多了!我也在想同样的事情,我在这里没有做太多的计算,只是设置和获取,如果这可能会导致速度缓慢。的确
def find_denomination_combinations_blckknght(amount, denominations):
    memo = {0: [[]]} # prefill value for base case of calculate_combinations where amt==0

    def calculate_combinations(amt):
        if amt not in memo:
            memo[amt] = []
            for denomination in denominations:
                new_amt = amt - denomination
                if new_amt >= 0:
                    for combination in calculate_combinations(new_amt):
                        memo[amt].append(combination + [denomination])
                # do nothing for new_amt < 0
        return memo[amt]

    return calculate_combinations(amount)