动态规划:力扣518. 零钱兑换 II(完全背包)

1、题目描述:
在这里插入图片描述
在这里插入图片描述

2、题解:

转化为完全背包:coins数组的元素为物品的重量,amount为背包的容量。而物品的数量无限。
状态定义:
dp[i][j] 若只使用前 i 个物品,当背包容量为 j 时,有 dp[i][j] 种方法可以装满背包。
对于本题,若只使用 coins 中的前 i 个硬币的面值,若想凑出金额 j,有 dp[i][j] 种凑法。
大致的伪代码:

int dp[N+1][amount+1]
dp[0][..] = 0
dp[..][0] = 1

for i in [1..N]:
    for j in [1..amount]:
        把物品 i 装进背包,
        不把物品 i 装进背包
return dp[N][amount]

状态转移:
dp[i][j] = dp[i - 1][j] + dp[i][j-coins[i-1]]
解释:
如果你不把这第 i 个物品装入背包,也就是说你不使用 coins[i] 这个面值的硬币,那么凑出面额 j 的方法数 dp[i][j] 应该等于 dp[i-1][j],继承之前的结果。
如果你把这第 i 个物品装入了背包,也就是说你使用 coins[i] 这个面值的硬币,那么 dp[i][j] 应该等于 dp[i][j-coins[i-1]]。
初始化:
dp[i][0] = 1,当总金额为0时,只有一种方案0.
伪代码如下:

for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= amount; j++) {
        if (j - coins[i-1] >= 0)
            dp[i][j] = dp[i - 1][j] + dp[i][j-coins[i-1]];
return dp[N][W]

写成python语音:

class Solution:
    def change(self, amount: int, coins: List[int]) -> int:
        #动态规划,完全背包
        n = len(coins)
        dp = [[0] * (amount + 1) for _ in range(n + 1)]
        for i in range(n + 1):
            dp[i][0] = 1
        for i in range(1,n + 1):
            for j in range(1,amount + 1):
                if j >= coins[i - 1]:
                    dp[i][j] = dp[i - 1][j] + dp[i ][j - coins[i - 1]]
                else:
                    dp[i][j] = dp[i - 1][j]
        return dp[-1][-1]

状态压缩:

class Solution:
    def change(self, amount: int, coins: List[int]) -> int:
        #动态规划,完全背包,空间优化
        n = len(coins)
        dp = [0] * (amount + 1)
        dp[0] = 1
        for i in range(n + 1):
            for j in range(1,amount + 1):
                if j >= coins[i ]:
                    dp[j] = dp[j] + dp[j - coins[i]]
        return dp[-1]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值