Ref: [Optimization] Dynamic programming【尋找子問題】html
Ref: [Optimization] Advanced Dynamic programming【優於recursion】緩存
顯然,本篇是關於」動態規劃"的部分。ui
要點:」個數「其實表明了「for循環」的層數。但「個數」不定,使用「遞歸」反而能解決這個問題,減小思路上的負擔。 this
import time def recMC(coinValueList, change):
minCoins = change if change in coinValueList: return 1 else: for i in [c for c in coinValueList if c <= change]: # 遍歷每個變量, 至關於多重循環。有意思的是,循環的深度是不肯定的; numCoins = 1 + recMC(coinValueList, change-i)
# 獲得這個遍歷分支的最終結果; if numCoins < minCoins: minCoins = numCoins
return minCoins start = time.time() print(recMC([1,5,10,25], 63)) end = time.time() print(end-start)
耗時:31秒。spa
要點:增長了」結果緩存「,效率極具增長。3d
代碼中的 knownResults 記錄了上圖中節點(某個change時)的最優/最小的值,做爲了記錄。code
def recDC(coinValueList, change, knownResults):
minCoins = change if change in coinValueList: knownResults[change] = 1 # 一個硬幣剛恰好 return 1 elif knownResults[change] > 0: return knownResults[change] else: for i in [c for c in coinValueList if c <= change]:
# numCoins = 1 + recDC(coinValueList, change-i, knownResults)
# 更新minCoins if numCoins < minCoins: minCoins = numCoins knownResults[change] = minCoins return minCoins
def main():
amnt = 2163 print(recDC([1,2,5,10,21,25], amnt, [0]*(amnt+1))) main()
耗時:0.01秒。htm
要點:不是從上到下的 (遞歸) 思惟,且容易棧溢出;而是從最小的狀況入手,逐漸擴大。blog
def dpMakeChange(coinValueList, change, minCoins, coinsUsed): # 首先,考慮全部的 "狀況",是從小到大考慮 for cents in range(change+1): coinCount = cents newCoin = 1 # 考慮這些 "狀況" 下的可行的 "硬幣" for j in [c for c in coinValueList if c <= cents]: # 拿掉這枚"硬幣",考慮 "上一個問題"的最優值 if minCoins[cents-j] + 1 < coinCount: coinCount = minCoins[cents-j] + 1 newCoin = j # 考慮過該 "狀況",更新記錄 minCoins[cents] = coinCount coinsUsed[cents] = newCoin return minCoins[change] def printCoins(coinsUsed, change): coin = change while coin > 0: thisCoin = coinsUsed[coin] print(thisCoin) coin = coin - thisCoin @fn_timer def main(): amnt = 2163 clist = [1,2,5,10,21,25] coinsUsed = [0]*(amnt+1) coinsCount = [0]*(amnt+1) # print("Making change for", amnt, "requires") print(dpMakeChange(clist, amnt, coinsCount, coinsUsed), "coins") # print("They are:") # printCoins(coinsUsed,amnt) # print("The used list is as follows:") # print(coinsUsed) main()
耗時:0.003秒。遞歸
End.