动态规划入门:用Python求最小硬币个数

问题描述: 
给出已有的硬币面额,和需用这些硬币组成的目标金钱数目,求能够组成这个目标金钱的最少硬币个数。 
问题分析: 
给定面额为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

 

你可能感兴趣的:(Python,算法分析与设计)