一尘不染

动态编程最佳找零

algorithm

我一直在审查一些动态编程问题,并且在寻找最小数量的硬币来进行更改方面,我一直很费时费力。

假设我们有价值分别为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行),那就太好了。谢谢!


阅读 173

收藏
2020-07-28

共1个答案

一尘不染

在我看来,代码正在解决每个美分值直到目标美分值的问题。给定目标值v和一组硬币C,您知道最佳硬币选择S必须采用的形式union(S', c),其中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]
2020-07-28