代码随想录算法训练营第四十四天| 完全背包 理论、518. 零钱兑换 II、377. 组合总和 Ⅳ

完全背包理论

完全背包简单来说就是物品的数量是无数个。可以对一个物品重复选取。

重点来了:由于前面对于0,1背包中,我们要采取逆序,这样才能保证不会重复选取,而对于完全背包来说,要采取正序

完全背包中有两种常考题,一种是组合,一种是排列,比如求装满背包的方式,在这些方式的定义中,若1,2 和2,1是同一种,那就是排列问题,组合问题使用常规的物品作为外层循环,背包作为内层循环

对于排列问题,则是使用背包作为外层循环,排列作为内层循环,注意,由于背包作为外层循环了,没法使用nums[i]作为起始点,只能用1,所以此处,写递推公式的时候,还需要加上判断语句,如j >= nums[i],这里的j仍旧是背包循环中的元素,其余与先前保持一致。

对于初始化问题,一般来说,我们是求最大值,求Max,初始化时,为了不影响取值,我们往往对元素初始化为0,但是有一种问题是,求满足背包的最小方案(元素最少),就是求min,那么我们初始化时应该取一个很大的值,比如float("INF")或者题目规定的最大取值。此处往往将dp[0]设为0

求最小方案问题时,递推公式中的,+value[i],此时应该换成+1,因为我们的目标是求方案长度(方案中元素数量),这体现的就是要求我们灵活改变公式

解题思路大致可以归为:1. 判断是01背包还是完全背包,通过物品数量决定,由此判断正逆序的使用。

2.判断是求最大数量还是常规问题,最大数量使用累加公式。

3. 求min还是max,决定初始化,设计到累加问题,一般来说dp[0]初始化为1。

4.若是完全背包,则判断是排列问题还是组合问题,决定内外层循环是啥

Leetcode - 518

硬币无限个,完全背包,正序。求所有可能,累加问题。

def change(self, amount: int, coins: List[int]) -> int:
        dp = [0] * (amount+1)

        dp[0] = 1
        for i in range(len(coins)):
            for j in range(coins[i],amount+1):
                dp[j]  += dp[j-coins[i]]

        return dp[-1]

Leetcode - 377

数据无限量使用,完全背包,正序。 求所有可能,累加问题。不同顺序就是不同的结果,很明显是排列问题,所以for循环我们要注意

 def combinationSum4(self, nums: List[int], target: int) -> int:
        dp = [0] * (target +1)
        dp[0] = 1

        for j in range(1,target +1):
            for i in range(len(nums)):
                if j >= nums[i]:        
                    dp[j] += dp[j-nums[i]]
            
            


        return dp[-1]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值