Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.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,我一直在复习一些动态规划问题,在寻找最小数量的硬币以进行更改方面,我很难将头脑集中在一些代码上 假设我们有价值25、10和1的硬币,我们正在兑换30。贪婪将返回25和51,而最优解将返回310。以下是关于此问题的书中的代码: def dpMakeChange(coinValueList,change,minCoins): for cents in range(change+1): coinCount = cents for j in [c for c in coin

我一直在复习一些动态规划问题,在寻找最小数量的硬币以进行更改方面,我很难将头脑集中在一些代码上

假设我们有价值25、10和1的硬币,我们正在兑换30。贪婪将返回25和51,而最优解将返回310。以下是关于此问题的书中的代码:

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必须是联合体’C的形式,其中C是C中的一些硬币,S’是v值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]

我认为第四行令人困惑,因为Python可以在列表中为iterable if conditionx中的x选择/筛选x,但在iterable:expression中的x标准中却做不到这一点


所以在我看来,有一种很俗气的方式,就是把两者焊接在一起。他们创建了一个列表理解,实际上没有转换,因此coinValueList中的c对c只是为了添加if c,如果你熟悉图论,这里有一种思考换币问题的方法可能很有用

假设您有一个按以下方式定义的图:

每个货币单位都有一个节点,例如从0到您感兴趣的值的便士,例如39美分或其他任何值。 任何两个节点之间都有一条弧,由允许使用的硬币的精确值隔开,例如,如果允许使用镍币,则节点之间的值介于34美分和29美分之间。 现在你可以把换硬币的问题看作是一个从你的兴趣值到零的最短路径问题,因为硬币的数量与你路径上的弧的数量完全相同

该算法没有使用图论术语,但它做的基本上是相同的事情:在图论框架中,外循环覆盖所有的分点或节点,内循环覆盖所有的弧——从当前弧到下一弧的coinValueList中的值。总之,他们正在寻找从零到您感兴趣的价值的最短路径。从零到零,从零到值,都不重要。然而,传统上我们向下搜索到零


当我意识到许多问题都可以转化为图形问题时,我才真正开始理解动态规划。不过,要小心——并非所有人都能做到。有些是超图,有些甚至可能不是超图。但这对我帮助很大。

什么是minCoins?不管怎么说,试图解决这个问题通常相当于背包问题,甚至可能更糟,因此在任何情况下找到最佳解决方案都会非常麻烦。解决方案可能取决于你能使用的硬币。在[l for l in list_Construction]中写变量主观上是不好的,只是因为我没见过太多……这很尴尬,但并不是很可怕。这只是缩小了名单的范围。同样的事情也可以通过下一行的if和continue来完成,但是什么都好,什么都清楚。基本上,我们知道用于兑换的硬币集合必须由coinValueList中的某个硬币加上b一堆其他硬币组成。所以,猜一个硬币换一个硬币,然后找出最好的方法来改变剩下的。很方便,剩下的比变化小,所以我们必须在早期的循环迭代中找到它的最佳解决方案。如果我们对a的每一个可能的猜测(即每一个不同的硬币价值)重复这一点,那么至少其中一个a加上相应的b必须是最优的。谢谢!这很简单,也解释得很好,我现在明白了这个问题是如何工作的。@Acjohnson 55当我这样称呼它时,它为什么会显示错误,比如dpMakeChange[1,7,10],23,7它应该返回3 7和2 1s@ActingAngel我匹配了@tect在原始问题中提供的方法签名。minCoins是一个大小更改+1的预分配数组。如果您对代码进行跟踪,那么它先前存在的内容并不重要。它可能根本不是一个参数,所以我理解您的困惑。
...
for eachCoinValue in filter(lambda x: x <= cents, coinValueList):
...
...
smallEnoughCoins = filter(lambda each: each <= cents)
for each in smallEnoughCoins:
    ...