动态规划----从硬币找零初识动态规划

问题1:有1,3,5三种硬币,输入待找币数,输出最少用币。(如输入15)

思路:可以把15划分为14+1,12+1,10+1三种情况来看,这样我们就把问题给缩小了,对14,12,10同理。最后我们有需要找1,这时就肯定只需1即可。

分析;设f(x)为找x元所需的最少硬币数,显然

f(0)=0,

f(1)=1,

f(2)=f(1)+1=f(2-1)+1,

f(3)=min{f(2)+1,f(0)+1}=min{f(3-1)+1,f(3-3)+1}

f(4)=min{f(3)+1,f(1)+1}=min{f(4-1)+1,f(4-3)+1}

f(5)=min{f(4)+1,f(2)+1,f(0)+1}=min{f(5-1)+1,f(5-3)+1,f(5-5)+1}

...

f(15)=min{f(15-1)+1,f(15-3)+1,f(15-5)+1}

...

f(x)=min{f(x-1)+1,f(x-3)+1,f(x-5)+1}

到这里,可以看出问题的关键了,就是min{f(x-1)+1,f(x-3)+1,f(x-5)+1},这条就是状态转移方程,将一个大问题不断变成小的子问题。

代码实现如下:

#输入x为找零数,coin为可用硬币
x = input()
x = int(x)
COIN = [1,3,5]

#创建列表以保存所需硬币数,+1是想直接从1开始,默认是0,长度会不够
f = [float('inf')]*(x+1)
f[0] = 0

#理财开始~
for i in range(f.__len__()):    #从f(0)开始计算
    for j in COIN:      #尝试各种硬币
        if i>=j:    #避免硬币过大
            if f[i-j]+1<f[i]:   #min{}操作
                f[i]=f[i-j]+1

print(f[x])


下面给出带找零方案的代码:

#输入x为找零数,coin为可用硬币
x = input()
x = int(x)
COIN = [1,3,5]

#创建列表以保存所需硬币数,+1是想直接从1开始,默认是0,长度会不够
# f = [[float('inf'),0]]*(x+1)
f=[]
for i in range(x+1):
    f.append([float('inf'),0])
f[0][0] = 0

#理财开始~
for i in range(f.__len__()):    #从f(0)开始计算
    for j in COIN:      #尝试各种硬币
        if i>=j:    #避免硬币过大
            if f[i-j][0]+1<f[i][0]:   #min{}操作
                f[i][0]=f[i-j][0]+1
                f[i][1]=j

print('total: '+str(f[x][0]))
while x != 0:
    print(str(x) + '----' +str(f[x][1]))
    x-=f[x][1]

初学python,列表的初始化可能写的不好。

小结

显然,这是一个动态规划的典型例子。阶段性地做出当前最优决策,这里就涉及到了一个最优子结构问题,如果没有最优子结构的问题是不可以用动态规划来解决的。

猜你喜欢

转载自blog.csdn.net/aaalswaaa1/article/details/81317792
今日推荐