添加链接描述
思路:
- dp[j]数组表示的是在金额达到 j 的时候所需要的最小硬币数
- 金额:背包容量,每个硬币的个数都为1:背包中物品的价值,硬币面额:物品重量
dp[j]=min(dp[j],dp[j-coin]+1)
class Solution:
def coinChange(self, coins: List[int], amount: int) -> int:
dp = [float('inf')] * (amount + 1)
dp[0] = 0
for coin in coins: # 遍历硬币
for j in range(coin, amount + 1): # 遍历金额
dp[j] = min(dp[j], dp[j - coin] + 1)
if dp[amount] == float('inf'):
return -1
return dp[amount]
01背包(物品有限个数)
1.dp数组含义
dp[i][j] 表示从下标为[0-i]的物品里任意取,放进容量为j的背包,价值总和最大是多少。
2.dp数组的初始化
- 首先设置dp数组为全0
- dp[i][0]全部设置为0(容量为0时背包里无价值)
- 第一行也就是dp[0][j]两种情况:
- 在
当前容量j<weight[0]
时,设置为0(理解为放不下,初始化的时候设置全0,这一部可以跳过) - 在
wight[0]<=bagweight
时,设置为weight[0](理解为可以放下) for (int j = weight[0]; j <= bagweight; j++) { dp[0][j] = value[0]; }
3.递推公式
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
4.遍历顺序
先遍历物品再遍历重量
for(int i = 1; i < weight.size(); i++) { // 遍历物品,从1开始因为第0行已经被初始化
for(int j = 0; j <= bagweight; j++) { // 遍历背包容量
if (j < weight[i]) dp[i][j] = dp[i - 1][j]; // 放不下当前这个物品
// 可以放下当前这个物品
else dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
}
}
滚动数组
for i in range(len(weight)): # 遍历物品
for j in range(bagWeight, weight[i] - 1, -1): # 遍历背包容量
dp[j] = max(dp[j], dp[j - weight[i]] + value[i])
完全背包(物品无限个数)
for i in range(len(weight)): # 遍历物品
for j in range(weight[i], bagWeight + 1): # 遍历背包容量
dp[j] = max(dp[j], dp[j - weight[i]] + value[i])