我一直在审查一些动态编程问题,并且在寻找最小数量的硬币来进行更改方面,我一直很费时费力。
假设我们有价值分别为25、10和1的硬币,并且我们将零钱更改为30。贪婪将返回25和5(1),而最优解将返回3(10)。这是本书中有关此问题的代码:
def dpMakeChange(coinValueList,change,minCoins): for cents in range(change+1): coinCount = cents for j in [c for c in coinValueList if c <= cents]: if minCoins[cents-j] + 1 < coinCount: coinCount = minCoins[cents-j]+1 minCoins[cents] = coinCount return minCoins[change]
如果有人可以帮我解决这段代码(我开始感到困惑的第4行),那就太好了。谢谢!
在我看来,代码正在解决每个美分值直到目标美分值的问题。给定目标值v和一组硬币C,您知道最佳硬币选择S必须采用的形式union(S', c),其中c是的一些硬币,C并且S'是的最佳解决方案v - value(c)(不好意思)。因此,该问题具有最佳子结构。动态编程方法是解决所有可能的子问题。它采取了cents * size(C)步骤,而如果您只是尝试强行使用直接解决方案,那么事情就会更加迅速。
v
C
S
union(S', c)
c
S'
v - value(c)
cents * size(C)
def dpMakeChange(coinValueList,change,minCoins): # Solve the problem for each number of cents less than the target for cents in range(change+1): # At worst, it takes all pennies, so make that the base solution coinCount = cents # Try all coin values less than the current number of cents for j in [c for c in coinValueList if c <= cents]: # See if a solution to current number of cents minus the value # of the current coin, with one more coin added is the best # solution so far if minCoins[cents-j] + 1 < coinCount: coinCount = minCoins[cents-j]+1 # Memoize the solution for the current number of cents minCoins[cents] = coinCount # By the time we're here, we've built the solution to the overall problem, # so return it return minCoins[change]