day42|完全背包问题 518. 零钱兑换 II 377. 组合总和 Ⅳ 322. 零钱兑换 279.完全平方数 139.单词拆分 多重背包问题


前言

小结

  1. 💕完全背包这里有趣的是排列顺序的问题
    • 如果要组合,就是先遍历物品再遍历背包,这样就不会有重复的【518零钱兑换】
    • 如果要排列,就是先遍历背包再遍历物品,这样就可以有重复的【377. 组合总和 Ⅳ】

完全背包问题

在这里插入图片描述

与01背包最大的区别在于物品可以放是无数个;

思路

区别:01背包是倒序的取法,因为只能放一次;那么这里完全背包可以放无数次,明显只能正序遍历;
完全背包物品和重量的循环的顺序是可以颠倒的

  • (我的理解)这里递推公式显示只与前面的元素有关【列向更新】,并且遍历重量是从前往后遍历,所以遍历顺序无关;下面给出了横向遍历和列向遍历的例子;
    在这里插入图片描述

  • 而01背包是从后往前遍历,如果后遍历物品的话,从后往前,前面的都还么有处理过呢,都是0,肯定是不对的;

方法一

下面是我自己写的,包括数据读取。

def Completebag(weights,values,bagweight):
    dp = [0] * (bagweight+1)
    for i in range(len(values)):
        for j in range(weights[i],bagweight+1,1):
            dp[j] = max(dp[j],dp[j-weights[i]]+values[i])
    return dp[bagweight]

if __name__ == "__main__":
    first_line = list(map(int,input().strip().split()))
    N,V  = first_line[0], first_line[1]
    weights, values = [], []
    for i in range(N):
        input_ = list(map(int,input().strip().split()))
        weights.append(input_[0])
        values.append(input_[1])
    # print(weights,values)
    result = Completebag(weights,values,V)
    print(result)

518. 零钱兑换 II

在这里插入图片描述

思路

🎈完全背包问题相较于01背包,最大的区别就是遍历顺序不同,别的几乎都一样

本题思路仍然是二维数组来想:我们先想象横向遍历,从前往后遍历,这就意味着前面的是一个考虑过放过物品i的了。所以递推公式还是一样的两个情况:重量为j的时候,不取物品i和取物品i的两个情况

0 1 2 3 4 5
1 1 1 1 1 1 1
2 1 1 2 2 3 3
5 1 1 2 2 3 4

dp五部曲

  1. dp含义: 装满背包容量为j的组合数
  2. 递推公式:前面讲过;dp[j] += dp[j - coins[i]];
  3. 初始化:dp[0]=1,这里设定为1【有争议的】,非0下标初始化为0
  4. 遍历顺序:这里必须先写遍历物品,再写遍历背包重量【也就是横向遍历】
    • 因为这里是组合而不是排列,如果先遍历物品的话是先看1,再看2,再看5这样,不会有重复的,例如2,1,2 和1,2,2这种,一定是组合,是符合的
    • 如果是先写遍历背包重量再写物品的话【纵向遍历】,就会出现2,1,2 和1,2,2的情况;具体原因见下面b站评论,讲得很好
      在这里插入图片描述

方法一

本题的重点是遍历顺序,必须要先物品再背包重量
初始化为1,一定为1否则不对

class Solution(object):
    def change(self, amount, coins):
        """
        :type amount: int
        :type coins: List[int]
        :rtype: int
        """
        dp = [0]*(amount+1)
        dp[0] = 1
        for i in coins:
            for j in range(i,amount+1):
                dp[j] = dp
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值