代码随想录算法训练营第四十四天 | 01背包问题理论基础、01背包问题滚动数组、416. 分割等和子集

背包问题其实有很多种,01背包是最基础也是最经典的,软工计科学生一定要掌握的。


01背包问题

思路

        直接上动态规划五部曲

1、dp数组及其下标的含义

对于背包问题,有一种写法, 是使用二维数组,即dp[i][j] 表示从下标为[0-i]的物品里任意取,放进容量为j的背包,价值总和最大是多少

2.确定递推公式

再回顾一下dp[i][j]的含义:从下标为[0-i]的物品里任意取,放进容量为j的背包,价值总和最大是多少。

那么可以有两个方向推出来dp[i][j],

  • 不放物品i:由dp[i - 1][j]推出,即背包容量为j,里面不放物品i的最大价值,此时dp[i][j]就是dp[i - 1][j]。(其实就是当物品i的重量大于背包j的重量时,物品i无法放进背包中,所以背包内的价值依然和前面相同。)
  • 放物品i:由dp[i - 1][j - weight[i]]推出,dp[i - 1][j - weight[i]] 为背包容量为j - weight[i]的时候不放物品i的最大价值,那么dp[i - 1][j - weight[i]] + value[i] (物品i的价值),就是背包放物品i得到的最大价值

所以递归公式: dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);

3.初始化

首先从dp[i][j]的定义出发,如果背包容量j为0的话,即dp[i][0],无论是选取哪些物品,背包价值总和一定为0。

再看其他情况。

状态转移方程 dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]); 可以看出i 是由 i-1 推导出来,那么i为0的时候就一定要初始化。

dp[0][j],即:i为0,存放编号0的物品的时候,各个容量的背包所能存放的最大价值。

那么很明显当 j < weight[0]的时候,dp[0][j] 应该是 0,因为背包容量比编号0的物品重量还小。

当j >= weight[0]时,dp[0][j] 应该是value[0],因为背包容量放足够放编号0物品。

4.确定遍历顺序

在如下图中,可以看出,有两个遍历的维度:物品与背包重量

动态规划-背包问题3

那么问题来了,先遍历 物品还是先遍历背包重量呢?

其实都可以!! 但是先遍历物品更好理解

5.举例验证,直接看链接里的吧。

代码
def test_2_wei_bag_problem1():
    weight = [1, 3, 4]
    value = [15, 20, 30]
    bagweight = 4

    # 二维数组
    dp = [[0] * (bagweight + 1) for _ in range(len(weight))]

    # 初始化
    for j in range(weight[0], bagweight + 1):
        dp[0][j] = value[0]

    # weight数组的大小就是物品个数
    for i in range(1, len(weight)):  # 遍历物品
        for j in range(bagweight + 1):  # 遍历背包容量
            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])

    print(dp[len(weight) - 1][bagweight])

test_2_wei_bag_problem1()

01背包滚动数组

 看链接吧,老是复制粘贴累了。


416.分割等和子集

本题是 01背包的应用类题目
思路

        就是01背包的应用,背包的大小是总和的一半,遍历每一个物品,看看遍历到最后能不能装满这个背包。

代码(二维版本在链接里)
class Solution:
    def canPartition(self, nums: List[int]) -> bool:
        if sum(nums) % 2 != 0:
            return False
        target = sum(nums) // 2
        dp = [0] * (target + 1)
        for num in nums:
            for j in range(target, num-1, -1):
                dp[j] = max(dp[j], dp[j-num] + num)
        return dp[-1] == target

相关推荐

最近更新

  1. TCP协议是安全的吗?

    2024-06-10 02:22:02       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-10 02:22:02       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-10 02:22:02       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-10 02:22:02       18 阅读

热门阅读

  1. 归一化在神经网络训练中的作用

    2024-06-10 02:22:02       7 阅读
  2. 基于fegin远程调用的重试功能

    2024-06-10 02:22:02       9 阅读
  3. 二分查找相关题目(c++)

    2024-06-10 02:22:02       8 阅读
  4. CSDN个人主页动态地图(前端/后端)

    2024-06-10 02:22:02       12 阅读
  5. 第06章_多表查询

    2024-06-10 02:22:02       10 阅读
  6. WebAPI 前端开发流程:深度解析与实践探索

    2024-06-10 02:22:02       7 阅读
  7. Spring Cloud Gateway CORS 跨域方案

    2024-06-10 02:22:02       12 阅读
  8. VB6.0 调用存储过程

    2024-06-10 02:22:02       11 阅读
  9. React antd 怎么封装权限按钮

    2024-06-10 02:22:02       10 阅读
  10. AppML 下载

    2024-06-10 02:22:02       8 阅读
  11. Oracle 数据库采用外部表监控查看分析 alert 告警

    2024-06-10 02:22:02       7 阅读
  12. Vue小程序项目知识积累(二)

    2024-06-10 02:22:02       7 阅读