动态规划应用--找零钱

文章目录

    • 1. 问题描述
    • 2. 问题分析
      • 2.1 回溯法求解
      • 2.2 DP状态转移方程法
      • 2.3 DP状态转移表法

1. 问题描述

找零问题,在贪心算法讲过。但是贪心不一定能得出最优解。假设有几种不同币值的硬币v1,v2,.……vn(单位是元)。如果要支付w元,求最少需要多少个硬币。比如,有3种不同的硬币,1元、3元、5元,我们要支付9元,最少需要3个硬币(3个3元的硬币)。

2. 问题分析

2.1 回溯法求解

/*** @description: 找零钱,需要张数最少,回溯法* @author: michael ming* @date: 2019/7/20 22:50* @modified by:*/
#include <iostream>
#define N 3
int rmb[N] = {1,9,10};//钞票面额
int amount[N];
int minAmount[N];
using namespace std;
void exchange(const int &targetMoney, int curMoney, int &minPiece, int piece)
{if(curMoney > targetMoney)//超过目标,返回return;if(curMoney == targetMoney)//达到目标金额{if(piece < minPiece){minPiece = piece;//更新最小张数for(int i = 0; i < N; ++i)minAmount[i] = amount[i];//获取每张钞票的张数}return;}for(int i = 0; i < N; ++i){//递归调用,拿取每张面额的钞票amount[i]++;exchange(targetMoney,curMoney+rmb[i],minPiece,piece+1);amount[i]--;//恢复上次的状态}
}
int main()
{int minPiece = 65535, piece = 0,targetMoney = 18, curMoney = 0;exchange(targetMoney,curMoney,minPiece,piece);cout << "凑成" << targetMoney << "元,最少需要:" << minPiece << "张(枚)。" << endl;int i = 0;while(i < N){if(minAmount[i] != 0)cout << minAmount[i] << "个" << rmb[i] << " ";i++;}cout << endl;cout << "----------------------" << endl;
}

在这里插入图片描述

2.2 DP状态转移方程法

由于上面的钞票面额可能不止3种,递归树是多叉树,所以状态转移表法画起回溯的递归图比较麻烦,我们采用状态转移方程法。

状态转移方程如下:

minPiece(targetMoney) = 1 + min{minPiece(targetMoney-rmb[0]), ... , minPiece(targetMoney-rmb[N-1])}

targetMoney = 18;//目标金额
rmb[N] = {1,9,10};//钞票面额
对于题目的情况,代入具体数值,状态转移方程如下

minPiece(18) = 1 + min{minPiece(18-1), minPiece(18-9) , minPiece(18-10)}= 1 + min{minPiece(17),minPiece(9),minPiece(8)}

DP(递归+备忘录)代码如下:

/*** @description: 找零钱,需要张数最少* @author: michael ming* @date: 2019/7/20 18:35* @modified by: */
#include <iostream>
#include <algorithm>
#include <memory.h>#define N 3
const int targetMoney = 18;//目标金额
int rmb[N] = {1,9,10};//钞票面额
int mem[targetMoney+1];//备忘录,存放最小张数
using namespace std;
int minP(int Money)
{if(Money < 0)//超过目标,返回很大的张数,表示不可能凑成return 65535;if(Money == 0)//达到目标金额return 0;if(mem[Money] > 0)//计算过了,直接读取备忘录return mem[Money];int minAmount[N];memset(minAmount,65535,N*sizeof(int));for(int i = 0; i < N; ++i){//递归调用,拿取每张面额的钞票minAmount[i] = minP(Money-rmb[i]);}sort(minAmount,minAmount+N);mem[Money] = minAmount[0]+1;//记录最小的张数return mem[Money];
}
int main()
{cout << "凑成" << targetMoney << "元,最少需要:"<< minP(targetMoney) << "张(枚)。" << endl;//如何打印出选取钞票的面额和张数???
}

在这里插入图片描述

2.3 DP状态转移表法

/*** @description: 找零钱,需要张数最少,dp状态表法* @author: michael ming* @date: 2019/7/21 20:01* @modified by: */
#include <iostream>
#include <algorithm>
#include <memory.h>#define N 3
const int targetMoney = 18;//目标金额
int rmb[N] = {1,9,10};//钞票面额,从小到大
using namespace std;
void exchange(int Money)
{int maxPiece = targetMoney/rmb[0];//最大张数int i, j, k;int (*states)[targetMoney+1] = new int [maxPiece][targetMoney+1];//memset(states,65535,maxPiece*(targetMoney+1)*sizeof(int));//上面错误!!!memset一般只付0或极大值for(i = 0; i < maxPiece; ++i)for(j = 0; j <= targetMoney; ++j)states[i][j] = 65535;//初始化for(k = 0, j = 0; j <= targetMoney; ++j){if(k < N && j == rmb[k]){//初始化第一行数据states[0][j] = 1;//一张rmbk++;}}for(i = 1; i < maxPiece; ++i)//动态规划{for(j = 0; j <= targetMoney; ++j)//上面一行的数据考下来states[i][j] = states[i-1][j];for(j = 0; j <= targetMoney; ++j){if(states[i-1][j] != 65535){for(k = 0; k < N; ++k){if(j+rmb[k] <= targetMoney && states[i-1][j+rmb[k]] > states[i-1][j]+1)states[i][j+rmb[k]] = states[i-1][j]+1;}}}}cout << "凑成" << targetMoney << "元,最少需要:"<< states[maxPiece-1][targetMoney] << "张(枚)。" << endl;//------------打印选择的信息---------------------------for(i = maxPiece-1; i >= 1 && states[i][targetMoney] == states[i-1][targetMoney]; --i);//此时i等于最早出现的答案处的行for(j = targetMoney; j > 0; ){if(i != 0){for(k = 0; k < N; ++k){if(states[i-1][j-rmb[k]] == states[i][j]-1){cout << "1张" << rmb[k] << " ";j = j-rmb[k];i--;break;}}}else{cout << "1张" << j << " ";break;}}delete [] states;//释放资源
}
int main()
{exchange(targetMoney);return 0;
}

在这里插入图片描述
在这里插入图片描述

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

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

相关文章

玩转算法之面试第九章-动态规划

动态规划&#xff1a; 9-12 斐波那契数列 对重复计算&#xff0c;进行优化&#xff0c;进行记忆化搜索 假设基本的问题已经被解决&#xff0c;依次内推。 动态规划&#xff1a;将原问题拆解成若干个子问题&#xff0c;同时保存子问题的答案&#xff0c;使得每个子问题只求…

领域应用 | 从本体论开始说起——运营商关系图谱的构建及应用

本文转载自公众号&#xff1a;中国联通大数据。联通大数据技术专家闫龙将从“本体论”说起&#xff0c;为大家介绍联通大数据关系图谱的构建与应用。一&#xff0e;本体论万维网之父Tim Berners-Lee教授在1998年将语义网络&#xff08;Semantic web&#xff09;带入人类的视线。…

史上最强多线程面试44题和答案:线程锁+线程池+线程同步等

最全BAT必考题答案系列 最全MySQL面试60题和答案 史上最全Spring面试71题与答案 史上最全Redis面试49题&#xff08;含答案&#xff09;:哨兵复制事务集群持久化等 分布式缓存RedisMemcached经典面试题和答案 最全Java锁详解&#xff1a;独享锁/共享锁公平锁/非公平锁乐观锁…

部门直推!百度大搜索招聘NLP、搜索方向算法工程师!

星标/置顶小屋&#xff0c;带你解锁最萌最前沿的NLP、搜索与推荐技术工作职责负责百度搜索排序相关性&#xff08;Relevance&#xff09;策略。 职位要求-了解主流机器学习算法。 -优秀的分析问题和解决问题的能力&#xff0c;对解决具有挑战性问题充满激情。 -C/C语言编程&…

POJ 1276 ATM凑钱(动态规划)(未解答)

文章目录1. 题目1.1 题目链接1.2 题目大意1.3 解题思路2. 代码2.1 Accepted代码1. 题目 1.1 题目链接 http://poj.org/problem?id1276 1.2 题目大意 需要凑的钱最多100000&#xff0c;面额最多10种&#xff0c;每种张数最多1000&#xff0c;面额最大不超过1000 1.3 解题思…

论文浅尝 | 为基于知识库的问答构建形式查询生成

论文笔记整理&#xff1a;刘晓臻&#xff0c;东南大学计算机科学与工程学院本科生。Citation: H.Zafar, G. Napolitano, and J. Lehmann. Formal query generation for questionanswering overknowledge bases. ESWC, 2018.https://link.springer.com/content/pdf/10.1007%2F97…

Java多线程系列(十一):ReentrantReadWriteLock的实现原理与锁获取详解

我们继续Java多线程与并发系列之旅&#xff0c;之前我们分享了Synchronized 和 ReentrantLock 都是独占锁&#xff0c;即在同一时刻只有一个线程获取到锁。 然而在有些业务场景中&#xff0c;我们大多在读取数据&#xff0c;很少写入数据&#xff0c;这种情况下&#xff0c;如…

这篇顶会paper,讲述了疫情期间憋疯的你和我

星标/置顶小屋&#xff0c;带你解锁最萌最前沿的NLP、搜索与推荐技术编 | 小轶2020年净忙着见证历史了。年初疫情爆发后&#xff0c;大家的生活模式也因为疫情发生了巨变。经历了史上最长假期&#xff0c;躺尸太久&#xff0c;到后来满脑子只想开学/复工。今年KDD会议上有一篇很…

论文浅尝 | Knowledge Vault: 全网规模的知识概率融合方法

论文笔记整理&#xff1a;吴桐桐&#xff0c;东南大学博士生&#xff0c;研究方向为自然语言处理。链接&#xff1a;https://www.cs.ubc.ca/~murphyk/Papers/kv-kdd14.pdf基于机器学习&#xff0c;Knowledge Vault不仅能够从多个来源&#xff08;文本&#xff0c;表格数据&…

java程序员的必用的9款开发工具

今天推荐java程序员开发利器&#xff0c;包含如如下&#xff1a; 开发环境&#xff1a; Eclipse IntelliJ IDEA IntelliJ在业界被公认为最好的java开发工具之一&#xff0c;尤其在智能代码助手、代码自动提示、重构、J2EE支持、各类版本工具&#xff08;git、svn等&#xff…

动态规划应用--搜索引擎拼写纠错

文章目录1. 字符串相似度1.1 莱文斯坦距离1.2 最长公共子串长度2. 计算编辑距离2.1 莱文斯坦距离2.2 最长公共子串长度3. 搜索引擎拼写纠错4. 练习题在 Trie树那节讲过&#xff0c;利用Trie可以进行关键词提示&#xff0c;节省输入时间。在搜索框中你不小心打错了字&#xff0c…

玩转算法之面试第十章-贪心算法

leetcode 455 分配饼干 尝试将最大的饼干给最贪心的朋友 如果满足&#xff0c;则1 如果不满足&#xff0c;则将最大的饼干给次贪心的朋友&#xff0c;一次类推 试图让最多的小朋友开心 在这里插入代码片 #include<iostream> #include<vector>using namespace …

论文浅尝 | 基于知识库的自然语言理解 04#

本文转载自公众号&#xff1a;知识工场。罗康琦&#xff0c;上海交通大学计算机系2019届博士&#xff0c;研究方向为自然语义理解和知识图谱。2012年获得华中科技大学软件工程学士学位&#xff0c;现就职于京东数据科学实验室&#xff08;Data Science Lab&#xff09;。他曾在…

BERT跨模态之后:占领了视觉常识推理任务榜单TOP 2!

星标/置顶小屋&#xff0c;带你解锁最萌最前沿的NLP、搜索与推荐技术文 | 小鹿鹿lulu编 | YY前言由于 BERT-like 模型在 NLP 领域上的成功&#xff0c;研究者们开始尝试将其应用到更为复杂的 多模态 任务上。要求模型除文本数据以外&#xff0c;还要接收其他模态的数据&#xf…

常见的算法面试问题以及代码实现

1 时间复杂度分析 一个简单的时间测试代码如下&#xff1a; #include<iostream> #include<cmath> #include<ctime>using namespace std;int main(){for(int x1;x<9;x){int npow(10,x);clock_t startTimeclock();int sum0;for(int i0;i<n;i)sumi;clock…

阿里P8架构师谈:高并发与多线程的关系、区别、高并发的技术方案

什么是高并发&#xff1f; 高并发&#xff08;High Concurrency&#xff09;是一种系统运行过程中遇到的一种“短时间内遇到大量操作请求”的情况&#xff0c;主要发生在web系统集中大量访问收到大量请求&#xff08;例如&#xff1a;12306的抢票情况&#xff1b;天猫双十一活动…

LeetCode 1. 两数之和(哈希)

文章目录1. 题目2. 解题1. 暴力解法2. 哈希法3. python3解答1. 题目 题目链接&#xff1a;https://leetcode-cn.com/problems/two-sum/ 给定一个整数数组 nums 和一个目标值 target&#xff0c;请你在该数组中找出和为目标值的那 两个 整数&#xff0c;并返回他们的数组下标。…

论文浅尝 | TuckER:基于张量分解的知识图谱补全

笔记整理&#xff1a;孙泽群&#xff0c;南京大学计算机科学与技术系&#xff0c;博士研究生。论文链接&#xff1a;https://arxiv.org/abs/1901.09590背景知识图谱是图结构的数据库&#xff0c;以三元组(es, r, eo)的形式存储事实&#xff0c;其中es和eo分别表示主语和宾语实体…

阿里Java P系列技术要求(P5-P7)

阿里p系列薪资&#xff08;最新数据比这个高1倍左右&#xff09; 阿里P5&#xff08;高级研发工程师&#xff09; 工作要求&#xff1a; 能独立完成日常工作&#xff0c;并能够对一些方案提出自己的建议。 基本考核就是能上手独立完成工作&#xff0c;熟练掌握。 技能要求…

如何配置一台深度学习工作站?

星标/置顶小屋&#xff0c;带你解锁最萌最前沿的NLP、搜索与推荐技术这篇文章主要介绍的是家用的深度学习工作站&#xff0c;典型的配置有两种&#xff0c;分别是一个 GPU 的机器和四个 GPU的机器。如果需要更多的 GPU 可以考虑配置两台四个 GPU 的机器。如果希望一台机器同时具…