def recMC(coinValueList,change):
minCoins = change
if change in coinValueList: # 最小规模,直接返回
return 1
else:
for i in [c for c in coinValueList if c <= change]:
# 减小规模:每次减去一种硬币面值挑选最小数量
numCoins = 1 + recMC(coinValueList, change-i) # 调用自身
if numCoins < minCoins:
minCoins = numCoins
return minCoins
print(recMC([1,5,10,25], 63))
def recMC(coinValueList,change,knownResults):
minCoins = change
if change in coinValueList: # 递归基本结束条件
knownResults[change] = 1 # 记录最优解
return 1
elif knownResults[change] > 0: # 算过的就会大于0
return knownResults[change] # 查表成功,直接用最优解
else:
for i in [c for c in coinValueList if c <= change]:
# 减小规模:每次减去一种硬币面值挑选最小数量
numCoins = 1 + recMC(coinValueList, change-i, knownResults) # 调用自身
if numCoins < minCoins:
minCoins = numCoins
# 找到最优解,记录到表中
knownResults[change] = minCoins
return minCoins
print(recMC([1,5,10,25], 63, [0]*64))
详细解释:https://zhuanlan.zhihu.com/p/139157497
def dpMakeChange(coinValueList, change, minCoins):
"""
coinValueList:一个有效的硬币值列表
change:找零金额
minCoins:每个找零金额所需的最小硬币数量列表,函数完成后,将包含从0到change值的所有值的解决方案
动态规划:其所求的最优解是由子问题的最优解构成的.
动态规划是自底向上的计算.
在找零递加的过程中,设法保持每一分钱的递加都是最优解,一直加到求解找零钱
数,自然得到最优解
"""
# 从1分开始到change逐个计算最少硬币数
for cents in range(1, change + 1): # 从1到63美分逐个计算
coinCount = cents # 初始化最小找零的硬币数,假设都用1美分找零,即123456789美分时找零硬币书就是123456789
# 2.减去每个硬币,向后查最少硬币数,同时记录总的最少数
for j in [c for c in coinValueList if c <= cents]: # j在硬币面值小于找零美分中挑选
if minCoins[cents - j] + 1 < coinCount: # 若(当前找零美分-硬币面值)对应的找零数 < 该找零钱数的初始化硬币数,则不需要初始化那么多的硬币数
coinCount = minCoins[cents - j] + 1 # 将最小找零硬币数改为最优列表的数值,即(当前找零美分-硬币面值)对应的找零数
# 3.得到当前最少硬币数,记录到表中
minCoins[cents] = coinCount
# minCoins[10] = 1,因为找零硬币有10美分的面值,所以找零数为10的时候只需要1个硬币
# for循环的过程为,先j=1,判断10-1后的9美分所需的最小硬币是不是比初始化的10个少,是,则所需最小硬币数变为9美分需要的硬币数+1(这个1是j对应的硬币数需要1个),即6个
# 接着判断j=5,判断10-5后的5美分需要的最小硬币数是不是比已有的6个少,是,则所需最小硬币数变为5美分需要的硬币数+1,即2个
# 接着判断j=10,判断10-10后的0美分需要的最小硬币数是不是比已有的2个少,是,则所需最小硬币数变为0美分需要的硬币数+1,即1个
# 返回最后一个结果
return minCoins[change]
print(dpMakeChange([1,5,10,25], 11, [0]*12))
# print(dpMakeChange([1,5,10,21,25], 63, [0]*64))
def dpMakeChange(coinValueList, change, minCoins,coinsUsed):
"""
coinValueList:一个有效的硬币值列表
change:找零金额
minCoins:每个找零金额所需的最小硬币数量列表,函数完成后,将包含从0到change值的所有值的解决方案
"""
# 从1分开始到change逐个计算最少硬币数
for cents in range(1, change + 1): # 从1到63美分逐个计算
coinCount = cents # 初始化最小找零的硬币数,假设都用1美分找零,即123456789美分时找零硬币书就是123456789
newCoin = 1 # 初始化一下新加硬币
for j in [c for c in coinValueList if c <= cents]: # j在硬币面值小于找零美分中挑选
if minCoins[cents - j] + 1 < coinCount: # 若(当前找零美分-硬币面值)对应的找零数 < 该找零钱数的初始化硬币数,则不需要初始化那么多的硬币数
coinCount = minCoins[cents - j] + 1 # 将最小找零硬币数改为最优列表的数值,即(当前找零美分-硬币面值)对应的找零数
newCoin = j # 对应最小数量,所减的硬币
minCoins[cents] = coinCount
coinsUsed[cents] = newCoin # 记录本步骤加的1个硬币
return minCoins[change]
def printCoins(coinsUsed, change):
coin = change
while coin > 0:
thisCoin = coinsUsed[coin]
print(thisCoin)
coin = coin - thisCoin
amnt = 63
clist = [1, 5, 10, 21, 25]
coinsUsed = [0] * (amnt + 1)
coinCount = [0] * (amnt + 1)
print('Making change for', amnt, 'requires')
print(dpMakeChange(clist, amnt, coinCount, coinsUsed), 'coins')
print('they are:')
printCoins(coinsUsed, amnt)
print('The used list is as follows:')
print(coinsUsed)