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

给定金额和面额的最小硬币数量

邢新
2023-03-14

给定一组面额和所需的总和我必须找到最低数量的硬币使该总和以及硬币的数量为每个面额

请帮忙!!

共有2个答案

丁豪
2023-03-14

代码中有3个错别字:

第一:

if coins[i] >= j 
    dp[i][j] := min(dp[i-1][j], dp[i][j-coins[i]])

这应该是:

 if coins[i] > j <-- HERE
        dp[i][j] := min(dp[i-1][j], dp[i][j-coins[i]])  

第二:同样在前面的代码中,min的第二部分缺少1,因此正确的代码为

if coins[i] > j
        dp[i][j] := min(dp[i-1][j], 1 + dp[i][j-coins[i]]) <-- HERE

第三:

while j is not equal to 0
    if dp[i-1][j] is equal to min
        i := i - 1
    else
        Print(coins[i])
        j := j - coins[I] 
      // <---- HERE
    end if
end while

在这里,我们应该将min重新分配到新单元格,因此正确的代码将是:

while j is not equal to 0
    if dp[i-1][j] is equal to min
        i := i - 1
    else
        Print(coins[i])
        j := j - coins[I]
        min = dp[I][j]    
    end if
end while

非常感谢的解决方案。

汤博
2023-03-14

确定该金额所需最小硬币数量的伪代码为:

Procedure coinChange(coins, total):
n := coins.length
dp[n][total + 1]
for i from 0 to n
    dp[i][0] := 0
end for
for i from 1 to (total + 1)
    dp[0][i] := i
end for
for i from 1 to n
    for j from 1 to (total + 1)
        if coins[i] > j                 //if the denomination is greater than total
            dp[i][j] := dp[i-1][j] 
        else                           //if the denomination is less than or equal to total
            dp[i][j] := min(dp[i-1][j], dp[i][j-coins[i]])
        end if
    end for
end for
Return dp[n-1][total]

并找出所需的面额:

Procedure printChange(coins, dp, total):
i := coins.length - 1
j := total
min := dp[i][j]
while j is not equal to 0
    if dp[i-1][j] is equal to min          //if the value came from the top we didn't choose current coin
        i := i - 1
    else
        Print(coins[i])
        j := j - coins[i]
    end if
end while

如果您想打印每个面额的数字,在打印硬币[i]之后,您需要打印dp[j]dp[j-硬币[i]的差值。代码的其余部分将是相同的。

此解决方案的完整说明以前可以在SO文档中找到,但现在已移至此处。

给定不同面额的硬币和总数,如果我们使用最少数量的硬币,我们需要组合多少硬币才能得到总数?假设我们有coins={1,5,6,8}total=11,我们可以使用{5,6}的两个硬币得到总数。这确实是获得11枚硬币所需的最低数量。我们还假设硬币的供应是无限的。我们将使用动态规划来解决这个问题。

我们将使用2D数组dp[n][总计1],其中n是我们拥有的不同面值硬币的数量。对于我们的例子,我们需要dp[4][12]。这里dp[i][j]表示如果我们有硬币从硬币[0]到硬币[i],得到j所需的最小硬币数。例如dp[1][2]将存储如果我们有硬币[0]和硬币[1],我们可以用来制作2的最小硬币数量是多少。让我们开始吧:

首先,对于第0列,可以通过不使用任何硬币来获得0。所以第0列的所有值都将是0。对于dp[0][1],我们在问自己,如果我们只有1面额的硬币,也就是硬币[0]=1,得到1需要的最小硬币数量是多少?答案是1。对于dp[0][2],如果我们只有1,得到2所需的最小硬币数量是多少。答案是2。类似dp[0][3]=3,dp[0][4]=4以此类推。这里要提到的一件事是,如果我们没有面额为1的硬币,可能会有一些情况,仅使用1枚硬币无法实现总数。为了简单起见,我们在示例中取1。第一次迭代后,我们的dp数组将看起来像:

        +---+---+---+---+---+---+---+---+---+---+---+---+---+
 (denom)|   | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10| 11|
        +---+---+---+---+---+---+---+---+---+---+---+---+---+
    (1) | 0 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10| 11|
        +---+---+---+---+---+---+---+---+---+---+---+---+---+
    (5) | 1 | 0 |   |   |   |   |   |   |   |   |   |   |   |
        +---+---+---+---+---+---+---+---+---+---+---+---+---+
    (6) | 2 | 0 |   |   |   |   |   |   |   |   |   |   |   |
        +---+---+---+---+---+---+---+---+---+---+---+---+---+
    (8) | 3 | 0 |   |   |   |   |   |   |   |   |   |   |   |
        +---+---+---+---+---+---+---+---+---+---+---+---+---+

接下来,对于dp[1][1],我们会问自己,如果硬币[0]=1,硬币[1]=5,那么获得1所需的最小硬币数量是多少?由于硬币[1]大于我们当前的总数,因此不会影响我们的计算。我们需要排除硬币[5],仅使用硬币[0]获得1。此值存储在dp[0][1]中。所以我们从顶部取值。我们的第一个公式是:

if coins[i] > j
    dp[i][j] := dp[i-1][j]

这个条件将是真实的,直到我们的总数是5在dp[1][5],在这种情况下,我们可以使5在两种方式:-我们采取5面值的硬币[0],这是存储在dp[0][5](从顶部)。-我们取1面值的硬币[1]和(5-5)=0面值的硬币[0]。

我们将选择这两个中的最小值。所以dp[1][5]=min(dp[0][5],1 dp[1][0])=1。为什么我们在这里提到0面值的硬币[0]将在我们的下一个位置显而易见。

对于dp[1][6],我们可以用两种方法制作6:-我们取6种面值的硬币[0],储存在顶部。-我们可以取1种面值的5,我们需要6-5=1来得到总数。使用面额为1和5的硬币获得1的最小方法数存储在dp[1][1]中,可以写成dp[i][j-硬币[i]],其中i=1。这就是为什么我们以这种方式编写以前的值。

我们将采用这两种方法中的最小值。因此,我们的第二个公式是:

if coins[i] >= j
    dp[i][j] := min(dp[i-1][j], dp[i][j-coins[i]])

用这两个公式我们可以把整张表填满。我们的最终结果将是:

        +---+---+---+---+---+---+---+---+---+---+---+---+---+
 (denom)|   | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10| 11|
        +---+---+---+---+---+---+---+---+---+---+---+---+---+
    (1) | 0 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10| 11|
        +---+---+---+---+---+---+---+---+---+---+---+---+---+
    (5) | 1 | 0 | 1 | 2 | 3 | 4 | 1 | 2 | 3 | 4 | 5 | 2 | 3 |
        +---+---+---+---+---+---+---+---+---+---+---+---+---+
    (6) | 2 | 0 | 1 | 2 | 3 | 4 | 1 | 1 | 2 | 3 | 4 | 2 | 2 |
        +---+---+---+---+---+---+---+---+---+---+---+---+---+
    (8) | 3 | 0 | 1 | 2 | 3 | 4 | 1 | 1 | 2 | 1 | 2 | 2 | 2 |
        +---+---+---+---+---+---+---+---+---+---+---+---+---+

我们要求的结果将存储在dp[3][11]中。程序将是:

Procedure coinChange(coins, total):
n := coins.length
dp[n][total + 1]
for i from 0 to n
    dp[i][0] := 0
end for
for i from 1 to (total + 1)
    dp[0][i] := i
end for
for i from 1 to n
    for j from 1 to (total + 1)
        if coins[i] > j
            dp[i][j] := dp[i-1][j] 
        else
            dp[i][j] := min(dp[i-1][j], dp[i][j-coins[i]])
        end if
    end for
end for
Return dp[n-1][total]

该算法的运行时复杂度为: O(n*总计),其中n是硬币的面额数。

要打印所需的硬币,我们需要检查:-如果值来自顶部,则当前硬币不包括在内。-如果值来自左侧,则当前硬币包括在内。

算法是:

Procedure printChange(coins, dp, total):
i := coins.length - 1
j := total
min := dp[i][j]
while j is not equal to 0
    if dp[i-1][j] is equal to min
        i := i - 1
    else
        Print(coins[i])
        j := j - coins[i]
    end if
end while

对于我们的例子,方向将是:

数值将为6,5。

 类似资料:
  • 在研究硬币更换问题后,我尽力实施解决方案。到目前为止,我的代码打印了给定金额所需的最低硬币数量。然而,它并不打印出每种硬币面额所需的数量。这是我的代码目前的样子: 我只是很困惑如何/在哪里填充numOfCoins[]。

  • 给定一个值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}。

  • 具体而言,问题是: 给定面额数组<代码>硬币[],每个硬币的限制数组<代码>限制[]和数量<代码>金额,返回所需的最小硬币数量,以获取<代码>金额,或者如果不可能,返回空值。另外,用溶液中使用的每个硬币的数量填充数组 这是我的解决方案: 但它一般不起作用。 我的问题是,例如,在这种情况下: 最佳解决方案是: 并且我的算法给出作为结果。换句话说,它失败了,每当在某种情况下,我将不得不使用比可能的更少

  • 我正在努力解决最小硬币兑换问题。问题是:给定一个值V,如果我们想改变为V美分,并且我们有无限量的C={C1,C2,...,Cm}值的硬币,做出改变的最小硬币数量是多少? 我建议的算法是: 从数组arr[1..V]开始,其中V是值: > 对于i:1中的所有值。。。V:计算为“i”值进行兑换所需的最小硬币数量。2.1. 这可以通过以下方式完成:对于所有j:1。。。。(i-1)arr[i]=min(ar

  • 我正在尝试实现以下CFC(coldfusion)代码: http://www.sitekickr.com/blog/integrating-paypal-payflow-pro-rest-api/ 我仍处于测试阶段,甚至没有尝试传递自己的变量,只是使用提供的CFSET示例。 我得到了这个错误: {“name”:“VALIDATION_ERROR”,“details”:[{“field”:“tran

  • 我得到了这个错误: {“name”:“validation_error”,“details”:[{“field”:“transactions[0].amount.total”,“issue”:“币种金额必须为非负数,可以选择精确包含小数点后2位,以”.“分隔,可选千位分隔符”,“,小数点前限7位”}],“message”:“请求无效-请参阅详细信息”,“information_link”:“htt