本次博客尝试以storyline的方式来写作,如有不足之处,还请多多包涵~~

问题的诞生

我们故事的主人公叫做丁丁,他是一个十几岁的小男孩,机智聪颖,是某某杂货店的小学徒。在他生活的国度里,只流通面额为1,3,4的硬币。复杂这家店的店长,叫做老王,是个勤奋实干的中年人,每天都要跟钱打交道。

有一天,他心血来潮,叫住正在摆放货物的丁丁,对他说道:“丁丁,你不是学过计算机方面的算法吗?我这里正好有个问题,不知你能解答不?”

一听到算法,丁丁的眼睛里闪出光芒,这正是自己的兴趣所在。于是,他连忙凑到柜台,好奇地问题:“什么问题啊?”

老王也不多说废话,他知道丁丁的聪慧之处,直接了当地说道:“你看啊,每次顾客们买完东西付款后,我们都要找零给他们,我们这边所有的硬币(1,3,4)都是充足的,我想知道一共有多少种找零方式?比如说找零为4的话,就有4=1+1+1+1=3+1=1+3=4共4种方式。”

乍听到这个问题,丁丁有点蒙圈了,因为4的情况是简单的,但是随着找零的面额增加,数量的变化就没有什么规律了。他示意掌柜出去走走,掌柜也欣然同意。

递归?动态规划?

此时我们的主人公正坐在湖边静静地思考,脑海中涌现出各种各样的计算机算法。突然,递归法进入了他的视野,对,就是递归法!他认真地整理着思路:

考虑面额为n的情况,假设n=x1+x2+...+xmn=x1+x2+...+xm.那么,只需考虑最后一个数xm=1,3,4xm=1,3,4的情形。当xm=1,3,4xm=1,3,4,剩下的面额为n−1,n−3,n−4.n−1,n−3,n−4.

假设面额为n的找零方式为f(n)f(n),则f(n)=f(n−1)+f(n−3)+f(n−4)f(n)=f(n−1)+f(n−3)+f(n−4),这样就能按照递归法来做了。

最后,只需要确定初值即可,f(0)=f(1)=f(2)=1,f(3)=2.f(0)=f(1)=f(2)=1,f(3)=2.

问题似乎到这就解决了,因为有了这个递推式,那么,直接定义一个函数就能解决问题了。等等,他想起昨天看到的博客“动态规划法(一)从斐波那契数列谈起”。对了,对于递推式,可以用动态规划法解决啊。于是,他顺手写了一下Python代码:

import time

# calculate the number of ways of integer n can be write the sum of 1,3,4

def sum_part_dp(n):

if n <= 2:

return 1

elif n == 3:

return 2

first = 1

second = 1

third = 1

fourth = 2

# repeat n-3 times

for _ in range(n-3):

answer = first + second + fourth

first = second

second = third

third = fourth

fourth = answer

return fourth

n = 40

t1 = time.time()

s = sum_part_dp(n)

t2 = time.time()

print('面额:%s,方法数:%s,耗时:%s'%(n, s, t2-t1))

他迅速地敲完了以上代码,运行,得到结果:

面额:40,方法数:119814916,耗时:0.0

Bingo,搞定!他满怀欣喜地将这个结果告诉了掌柜老王,老王看了,也禁不住点点头,心想:计算机算法真有用啊!

再一次的挑战

可是老王也是一个有想法的人,他看着丁丁这么干脆利落地解决了这个问题,决心再出一个难题考考他。他清了清喉咙,对丁丁说道:“刚才的问题解答得很棒啊,值得表扬 !但是现在呢,我这又有个麻烦事。每次找零,怎样找零才能使得找零的硬币数最少呢?”

丁丁笑而不语,他点了点头,就抱着他的电脑离开了。老王望着他离去的背影,心想:这个问题要是能解决,以后找零也就省了不少麻烦。不知这次丁丁要用多长时间?

有了上个问题的积累,丁丁对于解决这个问题满怀信心。还是跟刚才的解答方法一样,先用递归,假设面额为nn的找零所用最少硬币数为f(n)f(n),则f(n)=min{f(n−1)+1,f(n−3)+1,f(n−4)+1}.f(n)=min{f(n−1)+1,f(n−3)+1,f(n−4)+1}.采用自底向上的动态规划法,记录每个子问题的解,避免重复求解,这样就能得到f(n)f(n)的值了。那么,怎样才能记录每个子问题的解呢?用Python中的字典啊!这样,硬币数量是得到了,可是具体的找零方式呢?不难,只要用一个变量记录刚才表达式中是取f(n−1)f(n−1)还是f(n−3)f(n−3)还是f(n−4)f(n−4),对应面额为1,3,4,再递归地求解下去即可。

他写下了Python代码:

# 找零钱问题

# 找零钱字典,key为面额,value为最小硬币数

change_dict = {}

# 动态规划法解决问题

# 时间复杂度:多项式时间

# 只求解最小的硬币数量

def rec_change(M, coins):

change_dict[0] = 0

s = 0

for money in range(1, M+1):

num_of_coins = float('inf')

for coin in coins:

if money >= coin:

# 记录每次所用的硬币数量

if change_dict[money-coin]+1 < num_of_coins:

num_of_coins = change_dict[money-coin]+1

s = coin #记录每次找零的面额

change_dict[money] = num_of_coins

return change_dict[M],s

# 求出具体的找零方式

# 用path变量记录每次找零的面额

def method(M, coins):

print('Total denomination is %d.'%M)

nums, path = rec_change(M, coins)

print('The smallest number of coins is %d.'%nums)

print('%s'%path, end='')

while M-path > 0:

M -= path

nums, path = rec_change(M, coins)

print(' -> %s'%path, end='')

print()

coins = (1, 3, 4)

method(50, coins)

运行结果如下:

Total denomination is 50.

The smallest number of coins is 13.

3-> 3-> 4-> 4-> 4-> 4-> 4-> 4-> 4-> 4-> 4-> 4-> 4

几分钟后,当掌柜老王看到这个结果后,惊讶得目瞪口呆!在这家小小的杂货店里,也许藏着一位计算机天才,他这样想到。

而我们的主人公呢?此时,他已经向着斜阳,走在县城的小道上,踌躇满志,准备着去外面的世界看一看~~

注意:本人现已开通两个微信公众号: 用Python做数学(微信号为:python_math)以及轻松学会Python爬虫(微信号为:easy_web_scrape), 欢迎大家关注哦~~

python找零钱问题_动态规划法(二)找零钱问题相关推荐

  1. python必备单词整理_别乱找了,Python常用单词Word合集,已经给你整理全了

    最近我在学python 为大家整理了一下python常用的词汇.在学习python过程中觉得很有趣喔.感兴趣的朋友可以私信我一起研讨. Python (发音:[ 'paiθ(ə)n; (US) 'pa ...

  2. python数据分析就业前景_数据分析师找工作的秘诀,从读懂招聘 JD 开始

    JD(job description缩写),在招聘中,最常用到的意思是岗位介绍和工作职责描述. JD让无数求职者头痛,数据分析师更是其中的头疼之最.这份工作门槛尚可,薪资不错,行业发展前景好,因此吸引 ...

  3. python顺序结构实验设计_实验二 顺序结构程序设计

    实验二 顺序结构程序设计(验证性实验)(二学时) Python 程序设计 实验报告 班级_物流192_________ 姓名_吴陈燕_________ 学号_3190505219__________成 ...

  4. python小球方案问题_十二个小球称重问题及其Python实现

    一.问题描述 在12个外观完全相同的小球中,有一个与其它球重量不同.如何只用一架天平找到这个球并判断它比其它球轻还是重?最少需要称几次?39个球呢? 二.问题分析 这是一个很经典的信息论问题,最开始的 ...

  5. feignclient对象找不到_为什么我找不到对象呢,一个33岁大龄剩女的疑惑

    小木是我朋友,属兔今年33了.不仅我觉的她很优秀,周围的人也觉得她很优秀,但就是现在还单身.下面是她的疑惑. 我各方面条件都还行,为什么找不到对象呢? 性格:温和,善良,阳光,有主见.(对待事物有自己 ...

  6. python顺序结构实验设计_实验二 顺序结构程序设计(验证性实验)

    安徽工程大学 Python程序设计实验报告 班级物流192 姓名 徐敏 学号 3190505232 成绩 _____ 日期 2020.3.22 指导老师 修宇 [实验名称] 实验二 顺序结构程序设计( ...

  7. python语言基础实验_实验二Python语言基础函数包练习.doc

    实验二Python语言基础函数包练习 实验 Python语言基础函数包练习:1208 学号: 实验目的 1.Python语言包,如math.NumPySciPy和Matplotlib等函数包的使用实验 ...

  8. python解决换零钱问题_多种解法解决“零钱兑换”问题

    最近在LeetCode上刷算法题,准备秋招.刷了一些题之后,发现有些题非常棒,能够将多种知识点结合在一起.本文就以"零钱兑换"问题为例,展示同一道题的多种不同解法. 零钱兑换问题 ...

  9. python大作业代码_大二期末python大作业有效代码不低于5000行是什么水平?

    6月30日更新 鉴于题主说老师已经收回对行数的要求,就请大家看过则罢,不要再点赞了(还有收藏的是什么鬼?).本文说的不过是一些投机取巧的伎俩,不值取,不可取. ~~~以下是原文~~~: 一个熟练工程序 ...

最新文章

  1. VC++ 打开文件夹,保存文件等对话框的调用
  2. OVS DPDK--Ring端口配置(五)
  3. ce5e.cn fadian.php,空包网 PHP mysql
  4. SAP CRM OData模型里的addressable为true的含义
  5. midi 音符对应表
  6. 如何在MySQL中设置外键约束以及外键的作用
  7. LeetCode Week 6:第 51 ~ 55 题
  8. Black Hat USA 2020 大会主议题大盘点(上)
  9. 创建了对嵌入的互操作程序集间接引用,无法嵌入互操作类型
  10. 机器学习:特征选择之RFormula(SparkMLlib中的RFormula)
  11. PCB小知识(1)-关于打接地孔
  12. html怎么设置视频不能快进,【浏览器插件】Video Speed Controller – 网页视频倍速、快进、回放功能0.07~16 倍...
  13. 大容量Flash型AT91系列ARM核微控制器
  14. 遥感卫星影像数据全色波段和多光谱波段
  15. TempDB 收缩方法
  16. PCB电路板布局方法总结
  17. 国内首个电子政务云平台落地
  18. 一个整数,个位是4,把4移动到首位,则变为原来4倍,那么这个数是?
  19. 菜根谭 全文 及译文
  20. OkHttp实现延时重试

热门文章

  1. 【从零开始学习计算机网络——计算机网络传输技术】
  2. 2017年第十五届Esri中国用户大会资料分享
  3. iReport属性为空时报表显示空白
  4. LIMS系统平台在第三方检测实验室中的意义
  5. 近距离参观VR与汽车技术的结合,了解汽车如何使用VR技术
  6. 数据库概念mongodb使用数据库CLUD操作
  7. 一口气挑了101个适合程序员玩耍的项目!国庆可以玩的很嗨啦
  8. Kubernetes:3步排查K8S Deployment故障
  9. 计算机专业重大和吉大,中国“计算机专业”高校排名,中科大不敌吉大,电子科技无缘前10...
  10. win10 安装 Linux子系统(WSL)