https://leetcode.cn/problems/coin-change/description/?envType=study-plan-v2&envId=top-interview-150
class Solution:
def coinChange(self, coins: List[int], amount: int) -> int:
dp = [float('inf')] * (amount + 1)
dp[0] = 0
for i in range(1, amount + 1):
for coin in coins:
if coin <= i:
dp[i] = min(dp[i], dp[i - coin] + 1)
return dp[amount] if dp[amount] != float('inf') else -1
完全揹包問題裸題
轉載自OI wiki
文章還提到了錯誤的演算法,為什麼會錯誤呢,看一下情況:
如果使用我之前提到的錯誤演算法(從小到大更新揹包容量)處理同一個例子,我們會看到不同的結果。錯誤的方法如下:
for i in range(1, n + 1): # 遍歷物品
for l in range(0, W - w[i] + 1): # 從小到大遍歷揹包容量
f[l + w[i]] = max(f[l] + v[i], f[l + w[i]])
還是使用之前的物品和揹包情況:
- 物品1:重量3,價值30
- 物品2:重量4,價值50
- 揹包的總容量是7
來看看使用錯誤方法時會發生什麼:
- 初始化
f[0...7]
為0。 - 處理物品1:
- 從容量0開始,只有容量3及以上的
f
可以被更新。 - 更新後,
f[3]=30
,f[4]=30
,f[5]=30
,f[6]=30
,f[7]=30
。
- 從容量0開始,只有容量3及以上的
- 處理物品2:
- 從容量0開始,對於每個
l
,f[l + 4]
可以被更新。 - 因為從小到大的更新方式,
f[4]
先被更新為50,然後在處理到l=4
時,f[8]
會被嘗試更新(儘管f[8]
超出了揹包的容量),而f[4]
作為之前更新過的值,能在此基礎上再加上物品2的價值,導致物品2被錯誤地考慮了兩次。
- 從容量0開始,對於每個
最終,f
陣列在容量4的位置上可能反映的是物品2被放入兩次的情況(實際上因為陣列索引不會到8,但邏輯上這種重複使用已經發生),如果揹包容量足夠大,你會看到類似的錯誤累加。
這個錯誤方法雖然在本例中因為揹包容量限制沒有顯現出非法值,但在更復雜或容量更大的情況下,會導致演算法錯誤地計算出某些物品可以被多次加入揹包,從而得到錯誤的最大價值。這種情況下,演算法的輸出不符合01揹包的定義,即每個物品至多被放入一次。