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

找零的两种问题

硬币找零问题,有两种。一种用贪心解决,一种用动态规划解决。
问题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,一经查实,立即删除!

相关文章

【线性dp】【决策优化】CH5E02

题面 给你一个n*m的矩阵&#xff0c;要求每一行选择一个数&#xff0c;并且第i行选择的位置a[i]一定要大于第i-1行选择的位置a[i-1]&#xff0c;求选取的数的总和为多少&#xff0c;输出一组字典序最小的a[1]到a[n]。1<n<m<100 链接&#xff1a;http://contest-hunter…

[密码学基础][每个信息安全博士生应该知道的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…

动态规划6个题目总结比较

对前面几道题目做一下总结。 问题枚举多阶段限制条件目标值0-1背包每种物品&#xff1a;放/不放每种物品一个阶段不能超过总重量w放完索引物品后&#xff0c;总重量最大双11每种物品&#xff1a;买/不买每种物品一个阶段w<总价格<3w放完索引物品后&#xff0c;总价格是大…

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

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

docker安装mysql5.6,安装redis3.2

安装mysql 拉取镜像 [rootlocalhost ~]# docker pull mysql:5.6 运行镜像 docker run -p 3306:3306 --name mysql -v /usr/local/mysql5.6/conf:/etc/mysql/conf.d -v /usr/local/mysql5.6/logs:/logs -v /usr/local/mysql5.6/data:/var/lib/mysql -e MYSQL_R…

第六十一期: 从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…

vue-cli 3.0

安装&#xff1a; npm i vue/cli -g 搭建项目&#xff1a; vue create vue-test 按需加载element-ui 1、npm i element-ui -S npm install babel-plugin-component -D 2、babel.config.js 文件中设置 module.exports { presets: [ vue/app, babel/env ], plugins: [ // elemen…

第六十二期:看完这篇还不了解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…

安防摄像头Onvif、RTSP、GB28181转web无插件直播卡顿分析

监控摄像头网络直播 越来越多人的开始讲普通安防摄像机接入网络流媒体服务器&#xff0c;进行网络直播。这方面的解决方案比较多&#xff0c;最近测试了一个比较轻巧的解决方案&#xff1a;LiveNVR。这个就是实现接入普通RTSP/Onvif的安防摄像机&#xff0c;转成RTMP和HLS流&am…

算法七——分治算法

文章出处&#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;那么都会…

[密码学基础][每个信息安全博士生应该知道的52件事][Bristol Cryptography][第32篇]基于博弈的证明和基于模拟的证明

这是一系列博客文章中最新的一篇&#xff0c;该文章列举了“每个博士生在做密码学时应该知道的52件事”:一系列问题的汇编是为了让博士生们在第一年结束时知道些什么。 在基于博弈的安全定义中&#xff0c;安全是由博弈过程定义的。博弈围绕着一些通用的原始元素展开&#xff0…