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

动态规划换币问题

严亮
2023-03-14

我在理解各种问题的动态规划解决方案方面存在问题,特别是硬币兑换问题:

“给定一个值N,如果我们想换N美分,并且我们有无限多个S={S1,S2,…,Sm}值的硬币,我们可以用多少种方式来换?硬币的顺序并不重要。

例如,对于N=4和S={1,2,3},有四种解决方案:{1,1,1},{1,1,2},{2,2},{1,3}。所以输出应该是4。对于N=10和S={2,5,3,6},有五个解:{2,2,2,2,2},{2,2,3,3},{2,2,6},{2,3,5}和{5,5}。所以输出应该是5。"

这个问题的另一个变体是,解决方案是满足数量的最小硬币数量。

这些问题看起来非常相似,但解决方案却大不相同。

进行更改的可能方式的数量:最佳子结构为DP(m,n)=DP(m-1,n)DP(m,n-Sm),其中DP是截至第m个硬币的所有硬币的解决方案数量,金额=n。

最小硬币数量:最佳子结构是DP[i]=Min{DP[i-d1],DP[i-d2],…DP[i-dn]}1,其中i是总量,d1。。dn代表每种硬币的面额。

为什么第一个需要二维阵列,第二个需要一维阵列?为什么改变方式数量的最佳子结构不是“DP[i]=DP[i-d1]DP[i-d2]…DP[i-dn]”,其中DP[i]是硬币可以获得的方式数量。我觉得这听起来合乎逻辑,但它给出了一个错误的答案。为什么在这个问题中需要硬币的第二维度,而在最小数量问题中不需要?

与问题的联系:

http://comproguide.blogspot.com/2013/12/minimum-coin-change-problem.htmlhttp://www.geeksforgeeks.org/dynamic-programming-set-7-coin-change/

提前谢谢。我访问的每个网站都只解释解决方案是如何工作的,而不是其他解决方案不工作的原因。

共有2个答案

齐学文
2023-03-14

这是一个很好的解释硬币兑换问题使用动态规划。

代码如下:

public static int change(int amount, int[] coins){
    int[] combinations = new int[amount + 1];

    combinations[0] = 1;

    for(int coin : coins){
        for(int i = 1; i < combinations.length; i++){
            if(i >= coin){
                combinations[i] += combinations[i - coin];
                //printAmount(combinations);
            }
        }
        //System.out.println();
    }

    return combinations[amount];
}
潘哲
2023-03-14

>

  • 让我们先谈谈方式的数量,DP(m,n)=DP(m-1,n)DP(m,n-Sm)。这确实是正确的,因为要么你可以使用mth面额,要么你可以避免它。现在你说我们为什么不把它写成DP[i]=DP[i-d1]DP[i-d2]...DP[i-dn].这将导致过度计数,让我们举一个例子,n=4 m=2,S={1,3}。现在根据你的解dp[4]=dp[1]dp[3]。(假设1是基本情况dp[1]=1)。现在dp[3]=dp[2]dp[0]。(同样dp[0]=1的大小写)。同样的dp[2]=dp[1]=1。因此,总的来说,你得到的答案是3,而它应该只有2((1,3)和(1,1,1,1))。这是因为第二种方法将(1,3)和(3,1)视为两种不同的解。第二种方法可以应用于订单重要的情况,这也是一个标准问题。
  • 对于你的第二个问题,你说最小面额可以通过DP[i]=Min{DP[i-d1],DP[i-d2],...DP[i-dn]} 1.这是正确的,因为在寻找最小面额,顺序或没有顺序并不重要。为什么这是线性/1-D DP,虽然DP阵列是1-D,但每个状态最多取决于m个状态,不像你的第一个解决方案,其中阵列是2-D,但每个状态最多取决于2个状态。所以在这两种情况下,运行时间(状态数*每个状态依赖的状态数)是相同的,它是O(nm)。所以两者都是正确的,只是你的第二个解决方案节省了内存。因此,您可以通过一维数组方法或通过使用递归dp(n,m)=min(dp(m-1,n),1dp(m,n-Sm))的二维方法找到它。(在第一次复发中使用min)


    希望我澄清了疑问,如果还有什么不清楚的话就发帖子。

  •  类似资料:
    • 这是我关于硬币更换问题的代码,用于打印一组硬币的总方式数和目标金额 我想知道是否有任何方法可以用相同的动态规划解决方案打印这些方法(借助内部构造的表或任何其他方法) 例如,如果一组硬币是[1,3,5],目标金额是6,那么总共有4种可能的方式。[1,1,1,1,1,1,1,],[1,1,1,3],[3,3],[1,5]]我希望这种方式的列表作为输出。

    • 我编写的代码使用动态规划解决了基本的硬币兑换问题,并给出了进行兑换所需的最小硬币数量。但是我想把每个硬币的数量存储在最小的数字里。 我试图做的是初始化数组,就像散列一样,只要找到,它就会增加的数量,即。但这并不是我想要的方式,因为它每次发现对应于时都会添加硬币。因此,在最终答案中,数字不是硬币的最终计数。 代码如下:

    • 但是我们不能这样做吗:(是给定的可用硬币的排序集,和是它的下标,是给定的最高价值硬币) 我写的东西有什么问题吗?虽然解决方案不是动态的,但不是更有效吗?

    • 在硬币系统C={c1,c2,…ck}中,应改变给定的数量x,以使每个硬币ci具有给定的重量wi。我们想计算可能变化的总重量。两种变化是不同的,如果他们包含在不同的顺序相同的硬币。 如何给出上述问题的动态规划递归?我知道最小硬币兑换问题的递归(即C(x)=min{C(x-C)1 for x

    • 问题-你会得到不同面额的硬币和总金额。写一个函数来计算你需要的最少数量的硬币来组成这个数量。那里有无限的硬币供应。 我的方法——我遵循了自上而下的方法,但是使用map stl进行记忆,我得到了TLE。请帮助找出误差和估计时间复杂度。 这是我的密码-

    • 我正在解决以下问题从hackerrankhttps://www.hackerrank.com/challenges/coin-change/problem 我无法解决这个问题,所以我看了社论,他们提到 T(i, m)=T(i, m-i)T(i 1, m) 我无法从整体上理解为什么这个解决方案在更高的层次上有效。(如CLRS中的证明或简单易懂的示例) 我写的解决方案如下 我的解决方案不起作用,因为有