[英]Dynamic Programming Optimal Coin Change
我一直在審查一些動態編程問題,並且在尋找最小數量的硬幣來進行更改方面,我一直費時費力。
假設我們有價值分別為25、10和1的硬幣,我們將零錢更改為30。貪婪將返回25和5(1),而最優解將返回3(10)。 這是本書中有關此問題的代碼:
def dpMakeChange(coinValueList,change,minCoins):
for cents in range(change+1):
coinCount = cents
for j in [c for c in coinValueList if c <= cents]:
if minCoins[cents-j] + 1 < coinCount:
coinCount = minCoins[cents-j]+1
minCoins[cents] = coinCount
return minCoins[change]
如果有人可以幫助我解決這段代碼(我開始感到困惑的第4行),那將很棒。 謝謝!
在我看來,代碼正在解決每個美分值直到目標美分值的問題。 給定目標值v
和一組硬幣C
,您知道最優硬幣選擇S
的形式必須為union(S', c)
,其中c
是來自C
某種硬幣,而S'
是v - value(c)
的最優解v - value(c)
(不好意思)。 因此,該問題具有最佳子結構 。 動態編程方法是解決所有可能的子問題。 它需要幾分cents * size(C)
步長,而如果您只是嘗試強行使用直接解決方案,則該過程會更快地崩潰。
def dpMakeChange(coinValueList,change,minCoins):
# Solve the problem for each number of cents less than the target
for cents in range(change+1):
# At worst, it takes all pennies, so make that the base solution
coinCount = cents
# Try all coin values less than the current number of cents
for j in [c for c in coinValueList if c <= cents]:
# See if a solution to current number of cents minus the value
# of the current coin, with one more coin added is the best
# solution so far
if minCoins[cents-j] + 1 < coinCount:
coinCount = minCoins[cents-j]+1
# Memoize the solution for the current number of cents
minCoins[cents] = coinCount
# By the time we're here, we've built the solution to the overall problem,
# so return it
return minCoins[change]
如果您熟悉圖論,這是一種思考硬幣更改問題的方法,該問題可能會有用。
假設您具有通過以下方式定義的圖形:
現在,您可以將硬幣兌換問題視為從您的關注價值降至零的最短路徑問題,因為硬幣數量將與路徑中的弧形數量完全相同。
該算法不使用圖論術語,但基本上是在做同樣的事情:外環遍及所有“分”(或圖論框架中的節點),而內環遍及所有“分”。從當前弧到下一個弧的弧(coinValueList中的值)。 總之,他們正在尋找從零到您感興趣的價值的最短路徑。 (將值減小到零,將值減小到零是無關緊要的。不過,傳統上我們會向下搜索到零。)
當我意識到可以將許多問題轉換為圖形問題時,我才真正開始理解動態編程。 (但是請注意,並非所有人都可以。有些是超圖,有些甚至還沒有。但是這對我很有幫助。)
我認為第四行令人困惑,因為雖然Python可以在列表理解中選擇/過濾(transform(x) for x in iterable if condition(x))
,則(transform(x) for x in iterable if condition(x))
,但for x in iterable:
表達式中的for x in iterable:
它的標准不能做到相同。
因此,人們繞過的一種(俗氣的imo)方法是將兩者焊接在一起。 他們創建了一個列表c for c in coinValueList
,實際上並沒有進行任何轉換(因此c for c in coinValueList
的c for c in coinValueList
)只是為了在它們上添加if c <= cents
子句。 然后將其用作for x in iterable:
表達式中for x in iterable:
的標准for x in iterable:
。 我懷疑那是您一些困惑的來源。
編寫該行的另一種方法可能是:
...
for eachCoinValue in filter(lambda x: x <= cents, coinValueList):
...
甚至更清楚地講,使用“意圖揭示變量”將是:
...
smallEnoughCoins = filter(lambda each: each <= cents)
for each in smallEnoughCoins:
...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.