当前位置: 首页 > 知识库问答 >
问题:

解决“计数变化”的递归记忆解决方案

胡霖
2023-03-14

我试图通过记忆来解决“计数变化”的问题。

考虑下面的问题:我们可以用多少种不同的方式来换取1美元,半价、四分之一、二分硬币、五分硬币和五分硬币?更一般地说,我们可以编写一个函数来计算使用任何一组货币面额改变任何给定金额的方法的数量吗?

以及递归的直观解决方案。

使用n种硬币改变a的数量的方法数

  1. 除第一种硬币外,其他所有硬币都可以换成硬币的方法,加上
  2. 使用所有n种硬币改变较小数量a-d的方法的数量,其中d是第一种硬币的面额
#+BEGIN_SRC python :results output
# cache = {} # add cache 
def count_change(a, kinds=(50, 25, 10, 5, 1)):
    """Return the number of ways to change amount a using coin kinds."""
    if a == 0:
        return 1
    if a < 0 or len(kinds) == 0:
        return 0
    d = kinds[0] # d for digit
    return count_change(a, kinds[1:]) + count_change(a - d, kinds) 
print(count_change(100))
#+END_SRC
#+RESULTS:
: 292

我试着利用记忆,

Signature: count_change(a, kinds=(50, 25, 10, 5, 1))
Source:   
def count_change(a, kinds=(50, 25, 10, 5, 1)):
    """Return the number of ways to change amount a using coin kinds."""
    if a == 0:
        return 1
    if a < 0 or len(kinds) == 0:
        return 0
    d = kinds[0]
    cache[a] = count_change(a, kinds[1:]) + count_change(a - d, kinds)
    return cache[a]

它适用于少数人,如

In [17]: count_change(120)
Out[17]: 494

在大数字上工作

In [18]: count_change(11000)                        
---------------------------------------------------------------------------
RecursionError                            Traceback (most recent call last)
<ipython-input-18-52ba30c71509> in <module>
----> 1 count_change(11000)

/tmp/ipython_edit_h0rppahk/ipython_edit_uxh2u429.py in count_change(a, kinds)
      9         return 0
     10     d = kinds[0]
---> 11     cache[a] = count_change(a, kinds[1:]) + count_change(a - d, kinds)
     12     return cache[a]

... last 1 frames repeated, from the frame below ...

/tmp/ipython_edit_h0rppahk/ipython_edit_uxh2u429.py in count_change(a, kinds)
      9         return 0
     10     d = kinds[0]
---> 11     cache[a] = count_change(a, kinds[1:]) + count_change(a - d, kinds)
     12     return cache[a]

RecursionError: maximum recursion depth exceeded in comparison

记忆解决方案有什么问题?

共有1个答案

宇文和昶
2023-03-14

在记忆版本中,count_change函数必须考虑在进行递归调用时可以使用的最高硬币索引,以便可以使用已经计算的值。。。

def count_change(n, k, kinds):
    if n < 0:
        return 0
    if (n, k) in cache:
        return cache[n,k]
    if k == 0:
        v = 1
    else:
        v = count_change(n-kinds[k], k, kinds) + count_change(n, k-1, kinds)
    cache[n,k] = v
    return v

你可以试试:

cache = {}
count_change(120,4, [1, 5, 10, 25, 50])

给494

而:

cache = {}
count_change(11000,4, [1, 5, 10, 25, 50])

产出:9930221951

 类似资料:
  • 我正在做一个小的个人数独游戏,并试图扩展它。 到目前为止,我使用递归回溯方法使“Solve”部分正常工作,每当它设法解决递归时,就会返回true。 现在我正在尝试构建一个独特的解决方案板生成器,我在网上找到了很多关于如何实现它的信息。 然而,我在第一步很挣扎,这是我的布尔递归回溯算法变成一个递归算法,它保留了一个可能解决方案的计数。这对于检查我生成的板是否是唯一的至关重要。 更重要的是,我意识到我

  • 编写一个方法writeChars,该方法接受整数参数n,并按如下方式输出n个字符。输出的中间字符应始终为星号(“*”)。如果要求您写出偶数个字符,则中间会有两个星号(“**”)。在星号之前,您应写出少于个字符(“ 我已经设法解决了这个问题,但不太明白一句话: 为什么是递归情况: n-2?而不是n-1?

  • 问题内容: 我正在尝试编写一种算法,以Java或Javascript创建合法的Sudoku板。两者都不起作用,我也不完全清楚为什么。 本质上,两个程序中的问题是x或y的增量都超过了其应有的幅度(跳过平方)。我一生无法弄清楚这是怎么发生的。如果需要,我可以提供完成JS解决方案的HTML。 我最好的猜测是它与我如何使用递归创建堆栈有关,但是据我所知,它 应该可以 工作。在我的旧代码中,有一个不正确的f

  • 我在这里编写了一个Python解决方案,它解决了以下问题:如何用最少数量的给定面额的硬币来制造给定数量的货币? 虽然我的解决方案有效,但当大于50或的长度大于5时,需要很长时间。我怎样才能加快代码的速度,使其能够在相当大的输入下工作?我是否错过了一个技巧或其他可以大大加快代码速度的东西?

  • 问题内容: 我有一个程序可以通过递归传递大量数据,例如1000个变量。递归将至少运行50或60次。我担心的是,由于没有足够的空间,是否有可能数据在内存位置上被覆盖,或者如果没有内存,那么我会得到一些例外,即程序内存已经用完(我没有收到这样的错误)? 是否存在错误的解决方案,因为该程序没有更多的内存并且在现有位置上被覆盖? 问题答案: 涉及两个存储区域:堆栈和堆。堆栈是保存方法调用的当前 状态 (即

  • 给定一个值N,如果我们想改变为N美分,并且我们有无限量的S={S1,S2,...,Sm}值的硬币,我们有多少种方法可以改变?硬币的顺序并不重要。不过还有一个额外的限制:你只能用正好是K的硬币换零钱。 例如,对于N=4,k=2和S={1,2,3},有两个解:{2,2},{1,3}。所以输出应该是2。 解决方案: 以上是递归解决方案。但是,我需要有关动态规划解决方案的帮助: 让表示与元素和硬币的总和。