思路解析
动态规划采取了一条更加有条理的方式来得到问题的解:
- 从最简单的“1分钱找零”的最优解开始,逐步递加上去,直到我们需要的找零钱数
- 在找零的递加过程中,设法保持每一分钱的递加都是最优解,一直加到所要求解的找零钱数,也就得到了最优 解
- 递加的过程要保持最优解的关键是:其依赖于更少钱数最优解的简单计算,而更少钱数的最优解在大数目之前已经得到保存下来了。
- 问题的最优解包含了更小子规模问题的最优解,这是一个问题可以用动态规划策略解决的必要条件。
动态规划的主要思想:
- 从最简单的情况开始到达所需找零的循环
- 每一步都依赖于以前的最优解来得到本步骤的最优解,一直到得到答案。
代码
# @author:wpk
# @time:2021-10-20
# @description: deal the problem change money with dp(动态规划)
import time
def dpMakeChange(coinValueList,change,minCoins):
# 从1分开始到change 逐个计算最少硬币数
for cents in range(1,change+1):
# 1、从初始化一个最大值(多少分全给成1分的兑换)
coinCount = cents
#2、减去每个硬币,向后查找最少硬币数,同时记录总的最少数
for j in [c for c in coinValueList if c <= cents]:# (依次取出 coinValueList中比兑换数小的钱币值,运行时,不符合取出c的钱币数目不会经过此循环)
if minCoins[cents-j]+1 < coinCount:
coinCount=minCoins[cents-j]+1
#3、得到当前最少的硬币数,记录到表中
minCoins[cents] = coinCount
print(cents,minCoins[cents])
# 3、返回最后一个结果,循环结束,得到最优解
return minCoins[change]
start = time.time()
coinValueList = [1,5,10,20,50,100]
# change = 6
change = 66
# res=dpMakeChange(coinValueList,66,[0]*7)
res=dpMakeChange(coinValueList,66,[0]*67)
end = time.time()
print(res)
print("在货币机制为%s的情况下,钱币数字%s的最小找零为%s,本次计算程序用时为:%s" %(coinValueList,change,res,(end-start)))
注:
minCoins这里预给的是一个元素值全为零的列表,根据change的大小调整包含索引值的大小