在我们使用递归算法时,可能会出现规模庞大的重复计算,用一个中间表记录每个计算过的最优解法,就可以避免大量的重复计算。中间结果记录可以很好解决找零兑换问题。实际上,这种方法还不能称为动态规划,而是叫做“memoization(记忆化/函数值缓存)”的技术提高了递归解法的性能。

1. 找零兑换的动态规划解法

动态规划算法采用了一种更有条理的方式来得到问题的解。
找零兑换的动态规划算法从最简单的“1分钱找零”的最优解开始,逐步递加上去,直到我们需要的找零钱数。
在找零递加的过程中,设法保持每一分钱的递加都是最优解,一直加到求解找零钱数,自然得到最优解。
递加的过程能保持最优解的关键是,其依赖于更少钱数最优解的简单计算,而更少钱数的最优解已经得到了。
问题的最优解包含了更小规模子问题的最优解,这是一个最优化问题能够用动态规划策略解决的必要条件。
originalamount找零兑换问题具体来说就是:

numCoins 就是当前需要找零的硬币个数。
1 5 10 25就是硬币的币值。
originalamount就是要找零的钱数。

例如用动态规划解决11分钱的兑换问题。

  1. 从1分钱兑换开始,逐步建立一个兑换表。

看这个表的顺序就是从上往下。

兑换5分钱的时候,最优解就是一个5分的硬币。

  1. 计算11分钱的兑换法,我们做如下几步:
  • 首先减去1分硬币,剩下10分钱查表最优解是1,共需要2个硬币
  • 然后减去5分硬币,剩下6分钱查表最优解是2,共需要3个硬币
  • 最后减去10分硬币,剩下1分钱查表最优解是1,共需要2个硬币

25分就不减了,因为明显 11 < 24,不可能用25分来找零。

  1. 通过上述最小值得到最优解: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:动态规划:找零兑换问题的动态规划解法并显示使用的硬币组合相关推荐

  1. 数据结构与算法(python)递归:找零问题

    参考自 MOOC数据结构与算法Python版 目录 一.什么是递归Recursion 1. 初识递归 1.1 数列求和 1.2 递归"三定律" 2. 递归的应用 2.1 任意进制转 ...

  2. Python数据结构与算法分析 第四章 递归 贪心 动态规划bp 记忆化搜索

    递归算法也总结出 三定律  1,递归算法必须有一个基本结束条件(最小规模问题的直接解决)  2, 递归算法必须能改变状态向基本结束条件演 进(减小问题规模)  3,递归算法必须调用自身 (解决减小了规 ...

  3. 动态规划找零问题O(nk)

    主要思路是,用一个数组coinsUsed[]来保存找i分钱所需的硬币数,(i==maxchange就是我们正在寻找的解),用一个数组lastCoin[]来保存哪一个硬币是最后用来得到最佳找零方案的信息 ...

  4. 找零兑换(递归解法)

    https://blog.csdn.net/nyz5211314/article/details/105990555

  5. Python笔记-使用SSIM找两张图不同及使用Opencv显示

    运行截图如下: 这里有几点要注意的: ①对比两张图片的函数SSIM具体是structural_similarity: Ⅰ:第一个参数和第二个参数是要对比的两张图片: Ⅱ:参数中有个full,默认为Tr ...

  6. python 找零问题 动态规划

    题目描述: 现有的钱币:coins=[1,2,5,7,10] 找零:change(假定为正整数) 求解:如何用最少的钱币进行找零 分析:可以使用动态规划 比如找零8元,可以将问题进行分解 dp[8]= ...

  7. python找零_python 找零问题 动态规划

    题目描述: 现有的钱币:coins=[1,2,5,7,10] 找零:change(假定为正整数) 求解:如何用最少的钱币进行找零 分析:可以使用动态规划 比如找零8元,可以将问题进行分解 dp[8]= ...

  8. Python 动态规划(DynamicProgramming)-硬币找零

    动态规划(DynamicProgramming)-硬币找零 文章目录 动态规划(DynamicProgramming)-硬币找零 1.动态规划 a.什么是动态规划 b.适用对象 2.硬币找零-Codi ...

  9. 用动态规划算法求解最少硬币问题 c语言,动态规划算法求解硬币找零问题

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 看着这代码怎么这么熟悉. package 动态规划找零; import java.util.Scanner; public class Main { pu ...

最新文章

  1. matlab学习——1.基本操作
  2. 计算机组成 面试 ---杂货铺
  3. 关于python语言和人工智能哪个说法不正确_在 Windows 7 操作系统中,下列说法错误的是( )。_计算机文化基础答案_学小易找答案...
  4. 关于Git下载上传项目的操作指令
  5. C# 与java区别总结 收集
  6. 为什么ps图片打开是色块_PS教程 我的PS我做主之山村调色
  7. shipyard安装
  8. python exec函数_Python3
  9. 公司应该鼓励怎样的内斗
  10. Attachments
  11. Channel实现原理分析
  12. 学习笔记-2-Review of Optimization-3-Quadratic
  13. Python 设置三维图形鼠标拖动旋转的方法
  14. Vue ElementUI el-scrollbar 嵌套 el-tree 出现横向纵向滚动条
  15. matlab 工具箱 径向基,径向基(matlab工具箱)
  16. 微信小程序开发错误代码
  17. JavaScript之 高性能读书笔记
  18. 图书管理系统 利用文件txt进行读写操作 文件操作
  19. oppo手机html文件管理,oppo手机文件管理里面的文件可不可以删除
  20. 统计给定的n个数中,负数,零和正数的个数。

热门文章

  1. Hbase入门教程和分布式的安装部署
  2. Boosting AdaBoost算法
  3. $route.push()多次点击跳转报错问题
  4. Java生成随机图片验证码工具类
  5. 计算机操作系统计算题及答案(5),5计算机操作系统练习题及答案.doc
  6. [深度学习][原创]yolact编译DCNv2错误解决方法
  7. 分享123个ASP整站程序源码,总有一款适合您
  8. 自签名多级证书亲测可用
  9. Opencv2.4.9源码分析——Stitching(四)
  10. 如何把普通的五比四的照片做成5寸照片