Python数据结构20:动态规划:找零兑换问题的动态规划解法并显示使用的硬币组合
在我们使用递归算法时,可能会出现规模庞大的重复计算,用一个中间表记录每个计算过的最优解法,就可以避免大量的重复计算。中间结果记录可以很好解决找零兑换问题。实际上,这种方法还不能称为动态规划,而是叫做“memoization(记忆化/函数值缓存)”的技术提高了递归解法的性能。
1. 找零兑换的动态规划解法
动态规划算法采用了一种更有条理的方式来得到问题的解。
找零兑换的动态规划算法从最简单的“1分钱找零”的最优解开始,逐步递加上去,直到我们需要的找零钱数。
在找零递加的过程中,设法保持每一分钱的递加都是最优解,一直加到求解找零钱数,自然得到最优解。
递加的过程能保持最优解的关键是,其依赖于更少钱数最优解的简单计算,而更少钱数的最优解已经得到了。
问题的最优解包含了更小规模子问题的最优解,这是一个最优化问题能够用动态规划策略解决的必要条件。
originalamount找零兑换问题具体来说就是:
numCoins 就是当前需要找零的硬币个数。
1 5 10 25就是硬币的币值。
originalamount就是要找零的钱数。
例如用动态规划解决11分钱的兑换问题。
- 从1分钱兑换开始,逐步建立一个兑换表。
看这个表的顺序就是从上往下。
兑换5分钱的时候,最优解就是一个5分的硬币。
- 计算11分钱的兑换法,我们做如下几步:
- 首先减去1分硬币,剩下10分钱查表最优解是1,共需要2个硬币
- 然后减去5分硬币,剩下6分钱查表最优解是2,共需要3个硬币
- 最后减去10分硬币,剩下1分钱查表最优解是1,共需要2个硬币
25分就不减了,因为明显 11 < 24,不可能用25分来找零。
- 通过上述最小值得到最优解:2个硬币
解决思路如下:
need_change = 65
init_min_coins = [0] * (need_change + 1) # 建一个空表
real_value_list = [1, 5, 10, 25]def dynamic_programming(change, min_coins, value_list):for current_change in range(1, change + 1):min_coins[current_change] = current_change # 最坏的情况是只用一分钱兑换for value in value_list: # 遍历每个币值if current_change >= value:if 1 + min_coins[current_change - value] < min_coins[current_change]:# 若使用当前币值时,需要的最小硬币个数最小,就更新最小硬币数表中的个数min_coins[current_change] = 1 + min_coins[current_change - value]return min_coins[change] # 直接查表,最后一个就是我们想要的结果print(dynamic_programming(need_change, init_min_coins, real_value_list))
我们注意到动态规划算法的dynamic_programming并不是递归函数。虽然这个问题是从递归算法开始解决,但最终我们得到一个更有条理的高效非递归算法。
动态规划中最主要的思想是:
- 从最简单情况开始到达所需找零的循环
- 其每一步都依靠以前的最优解来得到本步骤的最优解,直到得到答案
2. 找零兑换:动态规划算法扩展
前面的算法已经得到了最少硬币的数量,但没有返回硬币如何组合。
扩展算法的思路很简单,只需要在生成最
优解列表同时跟踪记录所选择的那个硬币币值即可。
在得到最后的解后,减去选择的硬币币值,回溯到表格之前的部分找零,就能逐步得到每一步所选择的硬币币值。
need_change = 63
init_min_coins = [0] * (need_change + 1) # 建一个空表
init_coins_used = [0] * (need_change + 1) # 建一个空表用于保存每一步新增的硬币币值
real_value_list = [1, 5, 10, 21, 25]def dynamic_programming(change, min_coins, value_list, coins_used):for current_change in range(1, change + 1):min_coins[current_change] = current_change # 最坏的情况是只用一分钱兑换for value in value_list: # 遍历每个币值if current_change >= value:if 1 + min_coins[current_change - value] <= min_coins[current_change]:# 若使用当前币值时,需要的最小硬币个数最小,就更新最小硬币数表中的个数min_coins[current_change] = 1 + min_coins[current_change - value]coins_used[current_change] = value # 当前使用的币值存入到表中return min_coins[change], coins_used # 直接查表,最后一个就是我们想要的结果def combination_values(change, coins_used):print(coins_used[change])while change > 1:# 每次显示并减去当前新增的硬币,就是回溯了使用的所有币值,即显示了每次新增的硬币的币值if coins_used[change - coins_used[change]] > 0:print(coins_used[change - coins_used[change]])change = change - coins_used[change]min_coins, coins_used = dynamic_programming(need_change, init_min_coins, real_value_list, init_coins_used)
print(min_coins)
print(coins_used)
combination_values(need_change, coins_used)
3
[0, 1, 1, 1, 1, 5, 5, 5, 5, 5, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 21, 21, 21, 21, 25, 25, 25, 25, 25, 25, 21, 21, 21, 21, 25, 25, 25, 25, 25, 25, 21, 21, 21, 21, 25, 25, 25, 25, 25, 25, 25, 21, 21, 21, 25, 25, 25, 25, 25, 25, 25, 21, 21]
21
21
21
参考
本文的知识来源于B站视频 【慕课+课堂实录】数据结构与算法Python版-北京大学-陈斌-字幕校对-【完结!】,是对陈斌老师课程的复习总结
代码是我自己写的,功能比较简单
Python数据结构20:动态规划:找零兑换问题的动态规划解法并显示使用的硬币组合相关推荐
- 数据结构与算法(python)递归:找零问题
参考自 MOOC数据结构与算法Python版 目录 一.什么是递归Recursion 1. 初识递归 1.1 数列求和 1.2 递归"三定律" 2. 递归的应用 2.1 任意进制转 ...
- Python数据结构与算法分析 第四章 递归 贪心 动态规划bp 记忆化搜索
递归算法也总结出 三定律 1,递归算法必须有一个基本结束条件(最小规模问题的直接解决) 2, 递归算法必须能改变状态向基本结束条件演 进(减小问题规模) 3,递归算法必须调用自身 (解决减小了规 ...
- 动态规划找零问题O(nk)
主要思路是,用一个数组coinsUsed[]来保存找i分钱所需的硬币数,(i==maxchange就是我们正在寻找的解),用一个数组lastCoin[]来保存哪一个硬币是最后用来得到最佳找零方案的信息 ...
- 找零兑换(递归解法)
https://blog.csdn.net/nyz5211314/article/details/105990555
- Python笔记-使用SSIM找两张图不同及使用Opencv显示
运行截图如下: 这里有几点要注意的: ①对比两张图片的函数SSIM具体是structural_similarity: Ⅰ:第一个参数和第二个参数是要对比的两张图片: Ⅱ:参数中有个full,默认为Tr ...
- python 找零问题 动态规划
题目描述: 现有的钱币:coins=[1,2,5,7,10] 找零:change(假定为正整数) 求解:如何用最少的钱币进行找零 分析:可以使用动态规划 比如找零8元,可以将问题进行分解 dp[8]= ...
- python找零_python 找零问题 动态规划
题目描述: 现有的钱币:coins=[1,2,5,7,10] 找零:change(假定为正整数) 求解:如何用最少的钱币进行找零 分析:可以使用动态规划 比如找零8元,可以将问题进行分解 dp[8]= ...
- Python 动态规划(DynamicProgramming)-硬币找零
动态规划(DynamicProgramming)-硬币找零 文章目录 动态规划(DynamicProgramming)-硬币找零 1.动态规划 a.什么是动态规划 b.适用对象 2.硬币找零-Codi ...
- 用动态规划算法求解最少硬币问题 c语言,动态规划算法求解硬币找零问题
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 看着这代码怎么这么熟悉. package 动态规划找零; import java.util.Scanner; public class Main { pu ...
最新文章
- matlab学习——1.基本操作
- 计算机组成 面试 ---杂货铺
- 关于python语言和人工智能哪个说法不正确_在 Windows 7 操作系统中,下列说法错误的是( )。_计算机文化基础答案_学小易找答案...
- 关于Git下载上传项目的操作指令
- C# 与java区别总结 收集
- 为什么ps图片打开是色块_PS教程 我的PS我做主之山村调色
- shipyard安装
- python exec函数_Python3
- 公司应该鼓励怎样的内斗
- Attachments
- Channel实现原理分析
- 学习笔记-2-Review of Optimization-3-Quadratic
- Python 设置三维图形鼠标拖动旋转的方法
- Vue ElementUI el-scrollbar 嵌套 el-tree 出现横向纵向滚动条
- matlab 工具箱 径向基,径向基(matlab工具箱)
- 微信小程序开发错误代码
- JavaScript之 高性能读书笔记
- 图书管理系统 利用文件txt进行读写操作 文件操作
- oppo手机html文件管理,oppo手机文件管理里面的文件可不可以删除
- 统计给定的n个数中,负数,零和正数的个数。
热门文章
- Hbase入门教程和分布式的安装部署
- Boosting AdaBoost算法
- $route.push()多次点击跳转报错问题
- Java生成随机图片验证码工具类
- 计算机操作系统计算题及答案(5),5计算机操作系统练习题及答案.doc
- [深度学习][原创]yolact编译DCNv2错误解决方法
- 分享123个ASP整站程序源码,总有一款适合您
- 自签名多级证书亲测可用
- Opencv2.4.9源码分析——Stitching(四)
- 如何把普通的五比四的照片做成5寸照片