問題:如果我們有面值為1元、3元和5元的硬幣若干枚,如何用最少的硬幣湊夠11元?
動態規劃的本質是將原問題分解為同性質的若干相同子結構,在求解最優值的過程中將子結構的最優值記錄到乙個表中以避免有時會有大量的重複計算。
例如硬幣組合問題,若求湊夠11元的最少硬幣數,可以先從湊夠0元、1元、2元……的子結構開始分析。
假設d(i)為湊夠i元所需最少硬幣數,則
d(0) = 0 理所當然
d(1) = 1 要湊夠1元,需要從面值小於等於1元的硬幣中選擇,目前只有面值為1元的硬幣
此時d(1) = d(0) + 1
d(2) = d(2 - 1) + 1 = 2, 從面值小於等於2元的硬幣中選擇,符合要求的硬幣面值為:1元。
此時d(2) = d(2-1) + 1
d(3) = d(3 - 3) + 1 = 1, 從面值小於等於3元的硬幣中選擇,符合要求的硬幣面值為:1元,3元。
此時有有兩種選擇:是否選擇含有面值3元的硬幣
含有3元硬幣:d(3) = d(3 - 3) + 1 = 1
不含3元硬幣:d(3) = d(3 - 1) + 1 = d(2) + 1 = 3
自然是選擇二者中較小值
依次類推...
就該問題總結一下,隨著要湊夠錢數的增加:
1.首先要知道所有不大於該錢數的面值,
2.對於每種面值的硬幣,求出當選擇乙個該面值的硬幣時所需的硬幣數
當選擇乙個硬幣後,所需硬幣數+1,所要湊夠的錢數=原所要湊的錢數-該硬幣面值,所要湊夠的錢數減少,求減少後要湊錢數最少所需硬幣數,屬於原問題的子結構,已求出解
3.在上述求出的結果集中,選擇最小值,即為要湊夠該錢數所需的最少硬幣數
由此可以看出,每個問題的最優值都是借其子結構的最優值得到的。
而該演算法的最小的子結構的最優解是已知的,即:當要湊錢數為0元時,最少需要0枚硬幣。
利用這個最小的子結構,通過遞推式便可求出所指定值湊夠錢數的最優值
上面所提到的遞推式,便是狀態轉移方程。利用已知狀態,不斷通過狀態轉移方程求解,便得到了最優值和最優解。
下面看一下硬幣組合問題的數學描述:
d(i)=min,其中i-vj >=0,vj表示第j個硬幣的面值,i表示要湊夠i元,d(i)表示湊夠i元最少需要的硬幣數。即:
0 i == 0 時min_coin_num(i) = coin_value(j)表示第j種硬幣的面值 i > 0 時
當總值total_value為i時, 對於所有的 coin_value(j) < i的硬幣j ,取min
最後,該演算法的python實現:
# 如果我們有面值為1元、3元和5元的硬幣若干枚,如何用最少的硬幣湊夠11元
__author__ = 'ice'
def select_coin(coin_value, total_value):
min_coin_num = [0]
for i in range(1, total_value + 1):
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
return min_coin_num
result = select_coin([1, 3, 5], 11)
print("coin number:" + str(result[-1]))
部落格:欠扁的小籃子
硬幣組合問題 動態規劃
如果我們有面值為1元 3元和5元的硬幣若干枚,如何用最少的硬幣湊夠11元?表面上這道題可以用貪心演算法,但貪心演算法無法保證可以求出解,比如1元換成2元的時候 首先我們思考乙個問題,如何用最少的硬幣湊夠i元 i 11 當i 0,即我們需要多少個硬幣來湊夠0元。由於1,3,5都大於0,即沒有比0小的幣...
動態規劃 硬幣問題
這是乙個固定重點的最長路和最短路問題,可用動態規劃問題來求解 代表硬幣總值,n代表硬幣總數,v陣列儲存硬幣各個面值,d代表從i出發到結點0的路徑的最長路徑長度或最短路徑長度 vis代表是否訪問過該結點 int n,s,v maxn d maxn vis maxn int dpmax int s re...
動態規劃 硬幣問題
2013 07 11 03 17 5610人閱讀收藏 舉報 演算法和資料結構學習 79 最少硬幣問題 假設有3種不同的硬幣,幣值分別是coinvalue 每一種硬幣的數量是有限的,分別是coinnum 給定乙個數值target 18,找出一種硬幣數最少的方法,輸出最少的硬幣數。思路 動態規劃。問題定...