问题描述:
给出已有的硬币面额,和需用这些硬币组成的目标金钱数目,求能够组成这个目标金钱的最少硬币个数。
问题分析:
给定面额为c=[c1,c2,…ck],给定金钱数目为s,s可以由c中任意可行面额组成,则k可以分成:
s - ci + ci ,其中i<=k,且ci<=s,这样问题就转化为组成 金额为s-ci的最少硬币个数,假设s-ci的最少硬币个数为m,由于ci为c中的数值,一次只能取一个,所以组成s的最少硬币个数为m+1,同理可以继续求解s-ci。于是,我们可以定义d[n]表示组成n的最少硬币个数,那么
d[n]=min([ d[s-ci]+1,其中i<=k,且ci<=s ] ),我们可以由1到n依次记录d[x],即自底向上,当我们再次用到d[x]就不必再次计算。
python代码:
第一种不记录兑换的面值,只记录最少硬币数
def leastCoins(c,s):
#初始化d数组,d[0]=0,其余为inf(无限大),共有s+1个元素
d=[float('inf') if i != 0 else 0 for i in range(s+1)]
#依次求出d[1],d[2],...,d[s]
for i in range(1,s+1):
#当c中元素均大于i时,说明i无法由c中任何元素构成,设置为inf
d[i]=min([d[i-cc]+1 if cc<=i else float('inf') for cc in c])
return d[s]
第二种,记录所兑换面值
def select_coin(coin_value, total_value):
min_coin_num = [0]
path = [0] * (total_value + 1)
for i in range(1, total_value + 1):
min_coin_num.append(float('inf'))
for value in coin_value:
if value <= i: # and min_coin_num[i - value] + 1 < min_coin_num[i]:
min_coin_num[i] = min_coin_num[i - value] + 1
path[i] = i - value
print(path)
while path[total_value] != 0:#总值减去path中的路径值,就是兑换硬币值
print(total_value - path[total_value], end=' ')
total_value = path[total_value]
print(total_value, end=' ')
return min_coin_num, path
result,path = select_coin([1, 3, 5], 16)
print("coin number:" + str(result[-1]))
print("coin number:" + str(result))
print("coin number:" + str(path))
参考:
https://blog.csdn.net/dl_007/article/details/83046088 https://blog.csdn.net/m0_37650263/article/details/78647384