首页 > 其他分享 >理解01背包的一维和二维

理解01背包的一维和二维

时间:2022-12-17 13:33:44浏览次数:62  
标签:遍历 weight int 二维 维和 01 物品 背包 dp

区分一维和二维

一维和二维的区分,并不是体现在数组的维数上!!!

而是体现在概念上:

  1. 二维指的是下标体现了两个方面:

    • 物品的选择
    • 关于背包容量
  2. 一维指下标仅代表:

    • 背包的容量

一维和二维的代码

二维

dp[i][j]表示 从下标为[0-i]的物品里任意取,放进容量为j的背包,背包价值总和最大是dp[i][j]


// weight数组的大小 就是物品个数
for(int i = 1; i < weight.size(); i++) { // 遍历物品
    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]);
    }
}

一维

dp[j]表示 背包容量为j 所能放的最大价值为dp[j]

for(int i = 0; i < weight.size(); i++) { // 遍历物品
    for(int j = bagWeight; j >= weight[i]; j--) { // 遍历背包容量
        dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
    }
}

二维优化到一维

关于一维的遍历顺序

  • 背包的遍历顺序必须是倒序

有两种理解方式:

  1. 正序会破坏上一层的状态

  2. 正序会导致重复放入同一件物品

正序会破坏上一层的状态

二维图示:

由此可见,

二维时,dp[i][j]只与上一层左上角部分状态有关系,不能破坏上一层状态;

一维时,当上一层状态压缩到这一层,也就是指dp[0-j]这一部分其实是上一层的状态不可以破坏,那么只能从后向前遍历。

正序会导致重复放入同一件物品

举一个例子:物品0的重量weight[0] = 1,价值value[0] = 5

如果正序遍历

dp[1] = dp[1 - weight[0]] + value[0] = 5

dp[2] = dp[2 - weight[0]] + value[0] = 10

此时dp[2]就已经是10了,意味着物品0被放入了两次,因此不能正序遍历

  • 既然会重复放入,由此可以引申出完全背包的写法
// 先遍历物品,再遍历背包
for(int i = 0; i < weight.size(); i++) { // 遍历物品
    for(int j = weight[i]; j <= bagWeight ; j++) { // 遍历背包容量
        dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
    }
}

关于背包和物品的嵌套顺序

  • 二维: 可以是背包嵌套物品,也可以是物品嵌套背包
  • 一维:只能是物品嵌套背包

由于背包一定是从后往前遍历,那么如果是背包嵌套物品,会导致背包只有一个物品

dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);中 先背包容量使得没有前一层状态

例题:LC474 一和零

题目

https://leetcode.cn/problems/ones-and-zeroes/

You are given an array of binary strings strs and two integers m and n.

Return the size of the largest subset of strs such that there are at most m 0's and n 1's in the subset.

A set x is a subset of a set y if all elements of x are also elements of y.

示例 1:

输入:strs = ["10", "0001", "111001", "1", "0"], m = 5, n = 3
输出:4
解释:最多有 5 个 0 和 3 个 1 的最大子集是 {"10","0001","1","0"} ,因此答案是 4 。
其他满足题意但较小的子集包括 {"0001","1"} 和 {"10","1","0"} 。{"111001"} 不满足题意,因为它含 4 个 1 ,大于 n 的值 3 。

示例 2:

输入:strs = ["10", "0", "1"], m = 1, n = 1
输出:2
解释:最大的子集是 {"0", "1"} ,所以答案是 2 。

Constraints:

  • 1 <= strs.length <= 600
  • 1 <= strs[i].length <= 100
  • strs[i] consists only of digits '0' and '1'.
  • 1 <= m, n <= 100

MY

我的错误在于没有正确理解背包的优化所在。

思路

这里背包的要求有两个要求,这是一个二维容量的背包:m个0,n个1

class Solution {
public:
    int findMaxForm(vector<string>& strs, int m, int n) {
         vector<vector<int>> dp(m + 1, vector<int> (n + 1, 0)); // 默认初始化0
        for (string str : strs) { // 遍历物品
            int oneNum = 0, zeroNum = 0;
            for (char c : str) {
                if (c == '0') zeroNum++;
                else oneNum++;
            }
            for (int i = m; i >= zeroNum; i--) { // 遍历背包容量且从后向前遍历
                for (int j = n; j >= oneNum; j--) {
                    dp[i][j] = max(dp[i][j], dp[i - zeroNum][j - oneNum] + 1);
                }
            }
        }
        return dp[m][n];
    }
};
  • 参考《代码随想录》

标签:遍历,weight,int,二维,维和,01,物品,背包,dp
From: https://www.cnblogs.com/hereskiki/p/16988866.html

相关文章

  • 01背包与完全背包问题
    01背包的两层循环外层是物品,内层是对于每一个背包容量的计算。因为01背包问题这个物品是不可以重复放置的,所以物品只循环一次,也就是在循环计算的过程中,只在一次循环中出现......
  • nginx 转发处理301,302 跳转
    ···如果后方服务器返回302,此时,如果不进行特殊处理,客户端也收到302,但是如果客户端访问不到内部的服务器就要让nginx主动跟随302的地址,把内容取给我们,这需要进行如下设置......
  • A_A01_001 KEIL4-KEIL5软件安装
    @目录一、软件下载二、交流学习三、防止电脑误删文件操作步骤四、KEIL4安装五、KEIL5安装六、注意事项一、软件下载KEIL4/KEIL5网盘链接戳它跳转提取码:omni二、交流......
  • 【阿里开发者】2018-2022年精选文章-后端篇
    2022年精选文章​​代码重构:面向单元测试​​​​从业务开发中学习和理解架构设计​​​​深度解读RocketMQ存储机制​​​​提升Java字符串编码解码性能的技巧​​​​解......
  • Visual Studio 2013 Nuget(扩展和更新)无法连接网络分析和解决方法
    原因:Nuget官方网站已经不支持http访问,只支持https,但是VS2013访问https默认使用的协议为Tls1.1,但是Nuget官方网站只支持Tls1.2,这是两边不匹配导致的问题。解决:具体步骤如......
  • SQL Server 2019的安装
    SQLServer2019的安装一、SQLServer2019下载SQLServer2019Express版本的官方地址:https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads二、SQLS......
  • shopex采集发布接口 shopex火车头数据采集器(20120812更新) 使用火车头接口技术一键批量
    shopex如何实现商品批量导入数据采集批量发布1 找供应商采购谈判给你进货价2 一键采集供应商给你的所有商品(批量采集产品价格、批量采集多图、批量......
  • PHP 获取二维数组中某个key的集合
    本文为代码分享,也是在工作中看到一些“大牛”的代码,做做分享。具体是这样的,如下一个二维数组,是从库中读取出来的。代码清单: 1.$user=array(2.array(3.'id'......
  • 2019 Yinchuan K
    K.LargestCommonSubmatrix题链其实这类题就是非常典因为他给出的是一个不重复的矩阵那么我们B都会对应A有且仅有一个位置我们抽象其B->A为一个特定的向量题意就转......
  • SQL2014出现无效的许可证数据,需要重新安装
    SQL2014出现如下状况时:我们需要做如下操作:我这里是因为visualstudio2010Shell失效引起找到SQL2014安装文件夹:路径:sql2014\cn_sql_server_2014_enterprise_editio......