动态规划——硬币找零思路

找零的两种问题

硬币找零问题,有两种。一种用贪心解决,一种用动态规划解决。
问题1:假设我们有 v1,v2,……,vn(单位是元)这些币值的硬币,它们的张数分别是 c1、c2、…, cn。我们现在要用这些钱来找零 w元,最少要用多少张纸币呢?

问题2:假设我们有几种不同币值的硬币 v1,v2,……,vn(单位是元)。如果我们要支付 w 元,求最少需要多少个硬币。比如,我们有 3 种不同的硬币,1 元、3 元、5 元,我们要支付 9 元,最少需要 3 个硬币(3 个 3 元的硬币)。

问题1有一个限制条件是不同面额的硬币的张数是有限制的,而问题2中没有这个限制。

问题1解决用贪心。选择小于w的,面值最大的硬币,来付钱。

问题2解决用动态规划。至于为什么不用贪心,我也不大明白。接下来重点描述问题2的解决方法。

回溯法解决问题2

回溯法1

因为多次用了回溯法,所以很自然想到,每次决定一种硬币,使用一种数量,会产生什么状态。
例如w=9,
在第0阶段,我可以决定1元,使用0张,产生一种状态:支付0元;1元,使用1张,产生一种状态:支付1元;1元,使用2张,产生一种状态:支付2元…
在第1阶段,我可以决定3元,使用0张,基于上一步的状态产生新的状态:支付0、1、2…元;使用1张,基于上一步的状态产生新的状态:1+3、2+3…
当支付金额等于9的时候,比较最少使用了多少个硬币。

public class CoinChange {//钱币种类private int[] coins = new int[]{1,3,5};private  int n = coins.length;//总金额private int total = 9;private int minCount = Integer.MAX_VALUE;private void f (int i,int coinCount,  int sum){if(sum==total){minCount = Math.min(minCount,coinCount);return;}if(sum>total){return;}if(i==n){return;}int maxCount = (total - sum)/coins[i];System.out.println(maxCount);for(int j=0;j<=maxCount;j++){f(i+1,coinCount+j,sum+coins[i]*j);}}public int findCoinCount(){f(0,0,0);return minCount;}}

回溯法2

我们还可以换一种思路。我们按照支付金额分阶段。
我们硬币种类有1 元、3 元、5 元。设F(9)表示想要支付9元最少需要几个硬币。F(9)可以从F(9-1)、F(9-3)、F(9-5)三个状态过来,分别在这三个状态+1,选择最低值就是F(9)最少需要支付多少个硬币。

定义状态转移公式:
F(S)=mini=0,1,2...n−1(F(S−ci))+1F(S)=min_{i=0,1,2...n-1}(F(S-c_i))+1F(S)=mini=0,1,2...n1(F(Sci))+1 ,subject to S−ci&gt;=0S-c_i&gt;=0Sci>=0
F(0)=0F(0)=0F(0)=0
F(S)=−1F(S)=-1F(S)=1,when n=0n=0n=0

上一种回溯中是以每次选择一种硬币作为阶段。这次是每次支付够1元,2元,3元…n元,为阶段

public class CoinChangeV3 {//钱币种类private int[] coins = new int[]{1,3,5};private  int n = coins.length;//总金额private int total = 9;private int f (int total){if(n==0) return -1;if(total == 0) return 0;int minCount = Integer.MAX_VALUE;for(int i=0;i<n;i++){if(coins[i]<=total){int  count = f(total-coins[i]);minCount = Math.min(count,minCount);}}return minCount==Integer.MAX_VALUE?-1:minCount+1;}public int findCoinCount(){return f(total);}
}

备忘录模式

基于上面的回溯画出这样的递归树。树中的每一个节点是一种状态,用f(total)表示。total表示当前方法要支付多少元。(这感觉不像是以前那种状态)我们看到(3). (5)都重复计算了很多次。可以采用备忘录模式,减少计算次数。

public class CoinChangeV3 {//钱币种类private int[] coins = new int[]{1,3,5};private  int n = coins.length;//总金额private int total = 9;private int f (int total,int[] memory){if(n==0) return -1;if(total == 0) return 0;if(memory[total] !=0) return memory[total];int minCount = Integer.MAX_VALUE;for(int i=0;i<n;i++){if(coins[i]<=total){int  count = f(total-coins[i],memory);minCount = Math.min(count,minCount);}}memory[total] =  minCount==Integer.MAX_VALUE?-1:minCount+1;return memory[total];}public int findCoinCount(){int[] memory = new int[total+1];return f(total,memory);}}

动态规划

根据动态转移方程计算。

	public int findCoinCountDp(){int max = total+1;int[] dp = new int[total+1];Arrays.fill(dp,max);dp[0] = 0;for(int i=1;i<=total;i++){for(int j=0;i<coins.length;j++){if(coins[j]<=i){dp[i] = Math.min(dp[i],dp[i-coins[j]]+1);}}}return dp[total]==max?-1:dp[total];}

放在最后的一点体会。将问题抽象为多阶段决策问题,要分清楚是按照什么分阶段。一般来讲是按照目标指标分阶段。例如支付9元最少需要多少个硬币,分阶段为支付8元最少需要多少个硬币,支付7元最少需要多少个硬币…。例如从(0,0)走到(n-1,n-1)最少需要多少步,目标是(n-1,n-1),前一步可以是(n-1,n-2)或者(n-2,n-1),知道他们的最少步数+1,就是目标值,所以可以按照到达的坐标分阶段。
按照某个指标做分阶段,回溯法枚举的时候不一定与此相关。回溯法枚举的时候,枚举的是选项。例如不同面值的硬币,不同的前进方向。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/424519.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[密码学基础][每个信息安全博士生应该知道的52件事][Bristol Cryptography][第25篇]使用特殊的素数定义GF(p)和GF(2^n)的方法

这是一系列博客文章中最新的一篇&#xff0c;该文章列举了“每个博士生在做密码学时应该知道的52件事”:一系列问题的汇编是为了让博士生们在第一年结束时知道些什么。 当实现密码学方案时&#xff0c;一个最频繁调用的操作就是模运算。不幸的是&#xff0c;尽管模块化的使用非…

第五十九期:如何在Windows 10中执行Windows Defender离线扫描?

如果你使用Windows并经常上网浏览&#xff0c;强烈建议使用防病毒/安全保护软件。Windows 10随带一款名为Windows Defender/Security的内置防病毒保护工具&#xff0c;在过去几年不断成熟&#xff0c;已成为一种优秀的安全解决方案。 作者&#xff1a;布加迪编译 如果你使用Wi…

[密码学基础][每个信息安全博士生应该知道的52件事][Bristol Cryptography][第26篇]描述NAF标量乘法算法

这是一系列博客文章中最新的一篇&#xff0c;该文章列举了“每个博士生在做密码学时应该知道的52件事”:一系列问题的汇编是为了让博士生们在第一年结束时知道些什么。 [1] Hankerson, Darrel, Scott Vanstone, and Alfred J. Menezes. “Guide to elliptic curve cryptography…

第六十一期: 从7600万个5G连接中,我们发现了7种最有前景的5G物联网应用

近日&#xff0c;物联网市场调研机构IoT Analytics调研了44种不同的5G物联网用例&#xff0c;预计到2025年&#xff0c;这些用例将覆盖7600万个5G节点&#xff0c;本文重点介绍了其中7种最有市场前景的5G物联网用例。 作者&#xff1a;物联网智库 5G是第五代移动通信技术&…

动态规划——变形的杨辉三角形

我们现在对杨辉三角进行一些改造。每个位置的数字可以随意填写&#xff0c;经过某个数字只能到达下面一层相邻的两个数字。 假设你站在第一层&#xff0c;往下移动&#xff0c;我们把移动到最底层所经过的所有数字之和&#xff0c;定义为路径的长度。请你编程求出从最高层移动…

第六十期:玩了分布式这么久,你不会连Kafka都不清楚吧

Kafka 现在在企业和互联网项目中的应用越来越多了&#xff0c;本篇文章就从 Kafka 的基础开始带你一展 Kafka 的宏图。 作者&#xff1a;cxuan Kafka 现在在企业和互联网项目中的应用越来越多了&#xff0c;本篇文章就从 Kafka 的基础开始带你一展 Kafka 的宏图。 图片来自 Pe…

[密码学基础][每个信息安全博士生应该知道的52件事][Bristol Cryptography][第29篇]什么是UF-CMA数字签名的定义?

这是一系列博客文章中最新的一篇&#xff0c;该文章列举了“每个博士生在做密码学时应该知道的52件事”:一系列问题的汇编是为了让博士生们在第一年结束时知道些什么。 第16篇博客给出了DSA&#xff0c;Schnoor和RSA-FDH签名方案的细节&#xff0c;但是签名方案是什么&#xff…

第六十二期:看完这篇还不了解Nginx,那我就哭了!

看完这篇还不了解Nginx&#xff0c;那我就哭了&#xff01; Nginx 同 Apache 一样都是一种 Web 服务器。基于 REST 架构风格&#xff0c;以统一资源描述符(Uniform Resources Identifier)URI 或者统一资源定位符(Uniform Resources Locator)URL 作为沟通依据&#xff0c;通过 …

[密码学基础][每个信息安全博士生应该知道的52件事][Bristol Cryptography][第30篇]大致简述密钥协商中的BR安全定义

这是一系列博客文章中最新的一篇&#xff0c;该文章列举了“每个博士生在做密码学时应该知道的52件事”:一系列问题的汇编是为了让博士生们在第一年结束时知道些什么。 在两方之间建密钥共享是一件密码学中古老的问题。就算只考虑定义也比标准加密困难的多。尽管古典的Diffie-H…

算法七——分治算法

文章出处&#xff1a;极客时间《数据结构和算法之美》-作者&#xff1a;王争。该系列文章是本人的学习笔记。 MapReduce本质就是一个分值算法。 什么是分治算法 分治算法的核心是&#xff1a;分而治之。也就是将原问题分解为n个规模较小&#xff0c;并且结构与原问题相似的子…

[密码学基础][每个信息安全博士生应该知道的52件事][Bristol Cryptography][第31篇]Game Hopping证明

这是一系列博客文章中最新的一篇&#xff0c;该文章列举了“每个博士生在做密码学时应该知道的52件事”:一系列问题的汇编是为了让博士生们在第一年结束时知道些什么。 关于安全证明, 目前主流的方法有安全归约证明 (由 single game 实现) 和 Game Hopping (由 game sequence 实…

第六十三期:放下你手里的代码,小心被抓!

放下你手里的代码&#xff0c;小心被抓。最近程序员圈子不乏这样的戏谑调侃。 作者&#xff1a;沈春泽、李加庆来源 放下你手里的代码&#xff0c;小心被抓。最近程序员圈子不乏这样的戏谑调侃。 图片来自 Pexels 原因是最近发生的多起涉及爬虫技术的公司被司法部门调查。近…

算法九——回溯算法

文章出处&#xff1a;极客时间《数据结构和算法之美》-作者&#xff1a;王争。该系列文章是本人的学习笔记。 理解回溯 在我们的一生中&#xff0c;会遇到很多重要的岔路口。在岔路口上&#xff0c;每个选择都会影响我们今后的人生。有的人在每个岔路口都能做出最正确的选择&…

Python小数据池

一. id is 二. 代码块三. 小数据池四. 总结一&#xff0c;id&#xff0c;is&#xff0c; 在Python中&#xff0c;id是什么&#xff1f;id是内存地址&#xff0c;那就有人问了&#xff0c;什么是内存地址呢&#xff1f; 你只要创建一个数据&#xff08;对象&#xff09;那么都会…

第六十四期:聊聊原子变量、锁、内存屏障那点事

突然想聊聊这个话题&#xff0c;是因为知乎上的一个问题多次出现在了我的Timeline里&#xff1a;请问&#xff0c;多个线程可以读一个变量&#xff0c;只有一个线程可以对这个变量进行写&#xff0c;到底要不要加锁?可惜的是很多高票答案语焉不详&#xff0c;甚至有所错漏。 …

数据结构九——栈

文章出处&#xff1a;极客时间《数据结构和算法之美》-作者&#xff1a;王争。该系列文章是本人的学习笔记。 1栈的定义 1.1 栈的定义 栈&#xff1a;后进者先出&#xff0c;先进着后出。就像一碟盘子&#xff0c;如果拿走一个盘子&#xff0c;拿走的一定是最后放上去的那个…

[密码学基础][每个信息安全博士生应该知道的52件事][Bristol Cryptography][第33篇]Bellcore攻击是如何攻击使用CRT的RSA的?

这是一系列博客文章中最新的一篇&#xff0c;该文章列举了“每个博士生在做密码学时应该知道的52件事”:一系列问题的汇编是为了让博士生们在第一年结束时知道些什么。 转载链接:https://www.cnblogs.com/zhuowangy2k/p/12245604.html

spring学习(14):Autowired的使用场景

CompactDisc类 package soundSystem;import org.springframework.stereotype.Component;Component public class CompactDisc {public CompactDisc() {super();System.out.println("compactdisc无参构造方法");}public void play(){System.out.println("正在播…

数据结构十——队列

文章出处&#xff1a;极客时间《数据结构和算法之美》-作者&#xff1a;王争。该系列文章是本人的学习笔记。 1 队列 队列&#xff1a;可以想象成排队买票&#xff0c;先来的人先买&#xff0c;后到的人站在队尾。先进者先出&#xff0c;这就是队列。 队列的操作&#xff1a…

[密码学基础][每个信息安全博士生应该知道的52件事][Bristol Cryptography][第34篇]描述攻击离散对数问题的baby-step/Giant-step方法

这是一系列博客文章中最新的一篇&#xff0c;该文章列举了“每个博士生在做密码学时应该知道的52件事”:一系列问题的汇编是为了让博士生们在第一年结束时知道些什么。 Baby-step/Giant-step是Dnaiel Shanks为解决DLP问题开发的算法。DLP问题已经是许多现代密码学的困难性基础。…