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

汇入DP解决方案-进行更改

公羊俊德
2023-03-14

最近我读了一个练习DP的问题。我想不出一个,所以我尝试了一个递归解决方案,后来我修改了这个解决方案,使用了记忆化。问题陈述如下:-

做出改变。你会得到n种硬币面值v(1)

我从这里得到了问题

我的解决办法如下:

def memoized_make_change(L, index, cost, d):
    if index == 0:
        return cost

    if (index, cost) in d:
        return d[(index, cost)]

    count = cost / L[index]
    val1 = memoized_make_change(L, index-1, cost%L[index], d) + count
    val2 = memoized_make_change(L, index-1, cost, d)

    x = min(val1, val2)
    d[(index, cost)] = x
    return x

这就是我如何理解我对这个问题的解决方案。假设面额以升序存储在L中。当我从结束迭代到开始时,我有一个选择,要么选择一个面额,要么不选择它。如果我选择它,我然后递归以满足剩余的金额与较低的面额。如果我不选择它,我递归以满足较低面额的当前金额。

无论哪种方式,在给定的函数调用中,我都会找到满足给定数量的最佳(最低计数)。

从这里开始,我可以在沟通思想过程以达成DP解决方案方面得到一些帮助吗?我不是像任何HW那样做,这只是为了好玩和练习。我也不需要任何代码,只需要一些解释思考过程的帮助就可以了。

[编辑]

我记得读到过这样一篇文章:函数调用是昂贵的,这就是为什么自下而上(基于迭代)可能是首选的原因。这个问题有可能吗?

共有2个答案

孔磊
2023-03-14

我建议考虑你正在构建的价值和你需要的价值之间的关系。

在这种情况下,您正在构建索引的值,成本基于:

index-1 and cost
index-1 and cost%L[index]

您正在搜索的是一种迭代选择的方法,这样您将始终预先计算出您需要的所有内容。

在这种情况下,您可以简单地将代码更改为迭代方法:

for each choice of index 0 upwards:
    for each choice of cost:
        compute value corresponding to index,cost

在实践中,我发现对于简单的问题,迭代方法可以显著更快(例如,可能是*4),因为它避免了函数调用和检查缓存中预先存在的值的开销。

柏正平
2023-03-14

在可能的情况下,这里有一种将记忆递归解决方案转换为“传统”自底向上DP解决方案的通用方法

首先,让我们表达我们一般的“记忆化递归解”。这里,x表示在每次递归调用中更改的所有参数。我们希望这是一个正整数的元组——在你的情况下,是(index,成本)。我省略了递归中的任何常量(在您的情况下,L),并且我假设我有一个全局缓存。(但是FWIW,在Python中,你应该只使用标准库函数工具模块中的lru_cache装饰器,而不是自己管理缓存。)

To solve for(x):
    If x in cache: return cache[x]
    Handle base cases, i.e. where one or more components of x is zero
    Otherwise:
        Make one or more recursive calls
        Combine those results into `result`
        cache[x] = result 
        return result

动态规划的基本思想是首先评估基本情况,然后向上工作:

To solve for(x):
    For y starting at (0, 0, ...) and increasing towards x:
        Do all the stuff from above

但是,当我们以这种方式排列代码时,会发生两件好事:

>

  • 只要正确选择y值的顺序(当然,当只有一个向量组件时,这是微不足道的),我们可以安排递归调用的结果总是在缓存中(即我们之前已经计算过了,因为y在循环的前一次迭代中有这个值)。因此,我们不实际进行递归调用,而是直接用缓存查找来替换它。

    由于y的每个组件将使用连续递增的值,并将按顺序放置在缓存中,因此我们可以使用多维数组(嵌套lists,或Numpy数组)来存储值,而不是使用字典。

    因此,我们得到如下结果:

    To solve for(x):
        cache = multidimensional array sized according to x
        for i in range(first component of x):
            for j in ...:
                (as many loops as needed; better yet use `itertools.product`)
                If this is a base case, write the appropriate value to cache
                Otherwise, compute "recursive" index values to use, look up
                the values, perform the computation and store the result
        return the appropriate ("last") value from cache
    

  •  类似资料:
    • 尝试为一般硬币更换问题编程一个DP解决方案,该解决方案还可以跟踪使用的硬币。到目前为止,我一直在努力给我所需的最低硬币数量,但不知道如何获得使用了哪些硬币以及使用了多少次。我尝试设置另一个表(布尔值),如果硬币被使用,但这似乎不能正常工作。有什么想法吗?

    • 我有一个练习: 您将获得不同面额的硬币和总金额。请编写一个函数来计算您需要的最少数量的硬币,以弥补该金额。如果硬币的任何组合都无法弥补该金额,请返回-1 例1: 我还谷歌了一个这样的解决方案: 我知道它是关于DP的,但是,我对它很困惑,比如,的含义是什么,为什么要添加,为什么要添加,为什么要添加1? 有人能用简单的英语指出出路吗?

    • 这是一个骇人听闻的问题:爱丽丝是一个幼儿园老师。她想给班上的孩子们一些糖果。所有的孩子坐成一行(他们的位置是固定的),每个人根据他(她)在班上的表现有一个评级分数。爱丽丝想给每个孩子至少一颗糖。如果两个孩子挨着坐,那么评分较高的那一个必须得到更多的糖果。爱丽丝想省钱,所以她需要尽量减少给孩子们的糖果总数。 测试数组:n=10,n个元素为[2 4 2 6 1 7 8 9 2 1]。我得到的答案是18

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

    • 本文向大家介绍Oracle常见问题解决方案汇总,包括了Oracle常见问题解决方案汇总的使用技巧和注意事项,需要的朋友参考一下 1、Oracle 11g ORA-12514:TNS:监听程序当前无法识别连接描述符中请求的服务 数据库服务器崩了,而且尝试重启服务和重启机器都解决不了问题 打开cmd窗口 2、Oracle 11g ORA-00119 ORA-00132 错误如下: 解决方案: 1)、

    • 我有一个我无法解决的组合问题。 给定一组向量和一个目标向量,为每个向量返回一个标量,以便集中缩放向量的平均值最接近目标。 编辑:权重w_i在范围[0,1]内。这是一个约束优化问题: 最小化d(平均(w_i*x_i),目标),条件是总和(w_i)-1=0 如果我不得不命名这个问题,它将是无界子集平均。 我已经研究过无界背包和类似的问题,但由于数字的相互依赖性,动态编程实现似乎是不可能的。 我还补充了