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

为什么我们应该使用带记忆的动态编程来解决-最小硬币数量来进行更改

谢洛城
2023-03-14

问题陈述:给定无限供应值为 {C1, C2, ..., Cn} 的硬币和一个总和,找到可以表示总和 X 的最小硬币数。

网络上的大多数解决方案都包括带有记忆的动态编程。以下是来自Youtube的一个例子:https://www.youtube.com/watch?v=Kf_M7RdHr1M

我的问题是:为什么我们不先对硬币数组进行降序排序,然后通过最小化总和直到达到0来开始递归探索?当我们达到0时,我们知道我们已经找到了需要的硬币来补足总数。因为我们按降序对数组进行了排序,所以我们知道我们总是会选择最大的硬币。因此,当总和第一次下降到0时,计数必须是最小的。

如果您帮助了解我的算法的复杂性并将其与具有记忆方法的动态编程进行比较,我将不胜感激。

对于simplicty,我们假设总会有一个“1美元”硬币,因此总会有一种方法来凑成这个总数。

import java.util.*;

public class Solution{
    public static void main(String [] args){
        MinCount cnt=new MinCount(new Integer []{1,2,7,9});
        System.out.println(cnt.count(12));
    }
}

class MinCount{
     Integer[] coins;

     public MinCount(Integer [] coins){
        Arrays.sort(coins,Collections.reverseOrder());
        this.coins=coins;
    }

     public int count(int sum){
        if(sum<0)return Integer.MAX_VALUE;
        if(sum==0)return 0;     
        int min=Integer.MAX_VALUE;
        for(int i=0; i<coins.length; i++){
            int val=count(sum-coins[i]);    
            if(val<min)min=val;
            if(val!=Integer.MAX_VALUE)break;
        }
        return min+1;
     }
}

共有3个答案

郗河
2023-03-14
#recursive solution in python
import sys
class Solution:
    def __init__(self):
        self.ans=0
        self.maxint=sys.maxsize-1
    def minCoins(self, coins, m, v):
        res=self.solve(coins,m,v)
        if res==sys.maxsize-1:
            return -1
        return res
        
    def solve(self,coins,m,v):
        if m==0 and v>0:
            return self.maxint
        if v==0:
            return 0
        
        if coins[m-1]<=v:
            self.ans=min(self.solve(coins,m,v-coins[m-1])+1,self.solve(coins,m-1,v))
            return self.ans
        else:
            self.ans=self.solve(coins,m-1,v)
            return self.ans
印宏阔
2023-03-14

我将用一些算法设计建议来补充已经提供给你的问题的答案。

您提出的解决方案是所谓的“贪婪算法”:一种问题解决策略,它在每个阶段做出局部最优选择,并希望找到全局最优。

在许多问题中,贪婪策略不会产生最优解。证明算法正确性的最佳方法是找到一个反例,例如“52美元”、“50美元”和“1美元”硬币的情况。为了找到反例,史蒂文·斯基纳在《算法设计手册》一书中给出了以下建议:

  • 小处着眼:当一个算法失败时,通常有一个非常简单的例子来说明它失败了。
  • 寻找弱点:如果提出的算法是“总是采取最大的”(即贪婪的算法)的形式,想想为什么这可能是错误的做法。特别。。。
  • 打个平局:打破贪婪算法的一种狡猾方法是提供所有大小相同的实例。这样,算法可能没有什么可以作为其决策的基础。
  • 寻求极端:许多反例是巨大和微小,左和右,少和多,近和远的混合体。验证或推理极端的例子通常比更混乱的例子更容易。
通煜祺
2023-03-14

假设你有价值1美元、50美元和52美元的硬币,你的总数是100美元。你提出的算法将产生一个使用49个硬币的解决方案(52美元1美元…1美元1);但是正确的最小结果只需要2个硬币($50$50)。

(顺便说一句,我认为写作是作弊

简单地说,我们假设总是有一枚“1美元”硬币,因此总有办法弥补这个数字。

当这不在问题陈述中时,因此在其他来源中不假设。这有点像问“为什么排序算法总是花很多精力来重新排列元素,而不仅仅是假设元素一开始的顺序是正确的?但碰巧的是,即使假设存在1美元的硬币也不能保证天真/贪婪的算法会找到最佳解决方案。

 类似资料:
  • 我正在尝试打印最小数量的硬币来进行更改,如果不可能,请打印-1 在这段代码中,变量int[]c(硬币数组)有面额,我可以用它来计算总金额。 INT总有总和,我需要拿出使用硬币(无限供应) 对于Sum:4759和Array:{3190836},正确的输出是:59,我的输出是:60 代码中有什么错误? 下面是我的递归解决方案,尝试在DP解决方案中应用相同的逻辑。这里的逻辑似乎也有问题。对于相同的输入,

  • 动态规划变更问题(有限硬币)。我正在尝试创建一个以以下内容作为输入的程序: 输出: 输出应该是大小为1的数组,其中每个单元格代表我们需要改变单元格索引量的最佳硬币数。 假设数组的单元格位于index: 5,内容为2。这意味着为了给出5(INDEX)的变化,您需要2(单元格的内容)硬币(最佳解决方案)。 基本上,我需要这个视频的第一个数组的输出(C[p])。这与有限硬币的大区别是完全相同的问题。链接

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

  • 问题内容: 我正在学习React js( 如果是ii App.js模块),我必须导入React,因为 render() 方法用于将JSX转换为dom元素,而在Person.js中,我们正在创建箭头函数,然后将其导出以便它可以被导入并在App模块的render函数中使用,就像我们在React中导入的App模块一样,它将在模块person中转换JSX并在DOM上渲染,但是当我们在Person中删除以下

  • 所以我对编码不熟悉,我得到了一个任务,我需要做一个程序,用四分之一、一角、五分和一美分给不到一美元的零钱。然而,作业希望程序打印所需的最低硬币数量(例如,如果我输入58美分,那么输出应该是“2个25美分,1个镍和3个便士”,而不是“2个25美分,0个10美分,1个镍和3个便士”。本质上,如果没有某种硬币,那么程序就不应该打印它)。我一直在想如何制作它,这样程序就不会打印任何不必要的硬币。 这就是我

  • 问题:我很难找到达到特定金额所需的最低硬币数量。我很确定这是最简单的递归方式,使用动态编程方法,我基本上应该得到Math.min(“获取ACoin”、“离开ACoin”);不幸的是,我的代码不会终止,尽管我确实有在满足总和的条件下终止的if语句,硬币数组耗尽,或者如果总和结束。请查看下面的代码,让我知道我做错了什么,特别是为什么我的代码继续执行,直到它收到一个stackoverflow错误,尽管我