天天看點

找零錢問題【動态規劃】【python】

問題描述

設有n種不同面值的硬币,各硬币的面值存于數組T[1:n]中。現要用這些面值的硬币來找錢,可以實用的各種面值的硬币個數不限。當隻用硬币面值T[1],T[2],…,T[i]時,可找出錢數j的最少硬币個數記為C(i,j)。若隻用這些硬币面值,找不出錢數j時,記C(i,j)=∞。

« 程式設計任務

設計一個動态規劃算法,對1≤j≤L,計算出所有的C( n,j )。算法中隻允許實用一個長度為L的數組。用L和n作為變量來表示算法的計算時間複雜性

« 資料輸入

從螢幕輸入資料。輸入第1行中有1個正整數n(n<=13),表示有n種硬币可選。接下來的一行是每種硬币的面值。由使用者輸入待找錢數j。

« 結果輸出

 程式運作結束時,将計算出的所需最少硬币個數輸出到螢幕。

輸入示例 輸出檔案示例

3

1 2 5

9

3

建立二維動态規劃表

m為該次需要找的錢數,

找零錢問題【動态規劃】【python】

i為所用錢的種類數,

找零錢問題【動态規劃】【python】

邊界條件:

1)當找不開時,C[i][m]=∞

2)當m=0時,C[i][m]=0

遞歸關系:

找零錢問題【動态規劃】【python】

但是要注意找不開的情況,

隻有m>=t[i-1]時,才會走:

找零錢問題【動态規劃】【python】

m<t[i-1]直接用:

找零錢問題【動态規劃】【python】

程式設計檢驗的時候可以使用

3

2 3 5

6

這個例子

def give_coins(t,amount):
    maxc=(float('inf'))
    lent=len(t)
    C=[[maxc for i in range(amount+1)] for k in range(lent+1)]
    for i in range(lent+1):
        for m in range(amount+1):
            if i==0:  #初始化第一行
                C[i][m]=maxc
            elif m==0:  #初始化第一列
                C[i][m]=0
            else:
                if m-t[i-1]>=0:  
                    C[i][m]=min(C[i][m-t[i-1]]+1,C[i-1][m])

                else:
                    C[i][m]=C[i-1][m]
    return C

#回溯(未成功)
# def back(t,c):
#     select=[]
#     lent=len(t)
#     import numpy as np
#     minc=(np.min(C,axis=0))[-1]   #數組C最後一列的最小值
#     minarg=(np.argmin(C,axis=0))[-1]   #數組C最後一列最小值的下标
#     while minc>0:
#         minc-=t[lent-1]
#         minarg-=t[lent-1]


if __name__=="__main__":

    n=(int)(input())
    #小菜鳥剛學會把n個數輸入到清單中
    lista=[int(i) for i in input().split()]
    # print(lista)
    amount=(int)(input())
    result=give_coins(lista,amount)
    #動态規劃表
    # for list in result:
    #     print(list)
    import numpy as np
    minc=(np.min(result,axis=0))[-1]   #數組C最後一列的最小值
    print(int(minc))