简体   繁体   English

Python硬币更改动态编程

[英]Python Coin Change Dynamic Programming

I am currently trying to implement dynamic programming in Python, but I don't know how to setup the backtracking portion so that it does not repeat permutations. 我目前正在尝试在Python中实现动态编程,但是我不知道如何设置回溯部分,以便它不会重复排列。 For example, an input would be (6, [1,5]) and the expected output should be 2 because there are 2 possible ways to arrange 1 and 5 so that their sum is equivalent to 6. Those combinations are {1,1,1,1,1,1} and {1,5} but the way my program currently works, it accounts for the combinations displayed above and the combination {5,1}. 例如,输入为(6,[1,5]),预期输出应为2,因为有2种可能的方式来排列1和5,以使它们的总和等于6。这些组合为{1,1 ,1,1,1,1}和{1,5},但我的程序当前的工作方式是说明上面显示的组合和组合{5,1}。 This causes the output to be 3 which is not what I wanted. 这导致输出为3,这不是我想要的。 So my question is "How do I prevent from repeating permutations?". 所以我的问题是“如何防止重复排列?”。 My current code is shown below. 我当前的代码如下所示。

    import collections as c

    class DynamicProgram(object):
        def __init__(self):
            self.fib_memo = {}
            # nested dictionary, collections.defaultdict works better than a regular nested dictionary
            self.coin_change_memo = c.defaultdict(dict)
            self.__dict__.update({x:k for x, k in locals().items() if x != 'self'})
        def coin_change(self, n, coin_array):
            # check cache
            if n in self.coin_change_memo:
                if len(coin_array) in self.coin_change_memo[n]:
            return [n][len(coin_array)]

            # base cases
            if n < 0: return 0
            elif n == 1 or n == 0: return 1

            result = 0
            i = 0

            # backtracking (the backbone of how this function works)
            while i <= n and i < len(coin_array):
                result += self.coin_change(n-coin_array[i], coin_array)
                i += 1

            # append to cache
            self.coin_change_memo[n][len(coin_array)] = result

            # return result
            return result

Quick fix would be: 快速解决方法是:

result += self.coin_change(n-coin_array[i], coin_array[i:]) # notice coin_array[i:] instead of coin_array

But you want to avoid this as each time you will be creating a new list. 但是您要避免这种情况,因为每次您要创建一个新列表时。

Better fix would be: 更好的解决办法是:

Simply add a parameter lastUsedCoinIndex in the function. 只需在函数中添加参数lastUsedCoinIndex Then always use coins with index >= lastUsedCoinIndex from coin array. 然后,始终使用硬币阵列中index > = lastUsedCoinIndex的硬币。 This will ensure that the solutions are distinct. 这将确保解决方案各不相同。

Also you will have to make changes in your memo state. 另外,您将必须在备忘录状态中进行更改。 You are presently storing sum n and size of array (size of array is not changing in your provided implementation unlike the quick fix I provided, so its of no use there!!) together as a state for memo. 当前,您正在将sum nsize of array大小(与我提供的快速修复方法不同,在您提供的实现size of array大小没有改变,因此在这里没有用!)一起存储为备忘录的状态。 Now you will have n and lastUsedCoinIndex , together determining a memo state. 现在,您将拥有nlastUsedCoinIndex ,一起确定备忘录状态。

EDIT: 编辑:

Your function would look like: 您的函数如下所示:

def coin_change(self,coin_array,n,lastUsedCoinIndex):

Here, the only variables changing will be n and lastUsedCoinIndex . 在这里,唯一更改的变量将是nlastUsedCoinIndex So you can also modify your constructor such that it takes coin_array as input and then you will access the coin_array initialized by constructor through self.coin_array . 因此,您还可以修改构造函数,使其将coin_array作为输入,然后您将通过self.coin_array访问构造函数初始化的self.coin_array Then the function would become simply: 然后,该函数将变得简单:

def coin_change(self,n,lastUsedCoinIndex):

One of the way of avoiding permutation is to use the numbers in "non-decreasing" order. 避免排列的一种方法是按“非递减”顺序使用数字。 By doing so you will never add answer for [5 1] because it is not in "non-decreasing" order.And [1 5] will be added as it is in "non-decreasing" order. 这样,您将永远不会为[5 1]添加答案,因为它不是按“非递减”顺序排列的。而[1 5]将按“非递减”顺序添加。

So the change in your code will be if you fix to use the ith number in sorted order than you will never ever use the number which is strictly lower than this. 因此,如果您确定要按排序顺序使用第i个数字,则代码中的更改将是您永远不会使用严格低于此数字的数字。

The code change will be as described in Suparshva's answer with initial list of numbers sorted. 代码更改将按照Suparshva的答案所述进行, 其中包含初始数字列表。

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

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