DAY46:动态规划(八)01背包应用2:一和零(二维容量01背包)

news2024/11/22 12:11:18

文章目录

    • 474.一和零
      • 思路
        • 为什么不是多重背包而是01背包
        • 与之前01背包问题的区别
      • DP数组的含义
      • 递推公式(也是求最大值)
      • 初始化
      • 遍历顺序
      • 完整版
      • 总结

474.一和零

  • 本题属于 装满背包最多能有多少个物品 类型
  • 本题是容量有两个维度的背包,背包容量是m和n。物品的重量也是两个维度,对应上了背包的容量。
  • 本题也属于找最大值的问题,找最大值和基础01背包的找最大价值一样都是和自身对比找出历史最大值

给你一个二进制字符串数组 strs 和两个整数 m 和 n 。

请你找出并返回 strs最大子集的长度,该子集中 最多 有 m 个 0 和 n 个 1 。

如果 x 的所有元素也是 y 的元素,集合 x 是集合 y 的 子集

示例 1:

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

示例 2:

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

提示:

  • 1 <= strs.length <= 600
  • 1 <= strs[i].length <= 100
  • strs[i] 仅由 ‘0’ 和 ‘1’ 组成
  • 1 <= m, n <= 100

思路

本题题意是数组str里面找长度最大的子集,这个子集需要满足子集里面一共有m个0和n个1.

本题的背包思路是,我们可以把子集里需要的m个0n个1,想象成一种容器,那么这个问题,就转变成了:

装满m个0 n个1的容器,最多可以有多少个元素(物品)。也就是说,本题不同于前面的情况,属于问装满背包最多有多少个物品类型的题目。

(494.目标和 属于装满背包最多有多少个方案,416.分割等和子集 属于能否装满背包,1049.最后一块石头重量 属于背包最多能装多少

为什么不是多重背包而是01背包

本题因为是m个0,n个1,因此可能第一反应会是多重背包。

几种背包之间的关系:

在这里插入图片描述
多重背包是每个物品,数量不同的情况。01背包是每个物品只有一个(只能用一次),完全背包是每个物品有无限个

而本题中,strs 数组里的元素就是物品,每个物品都是一个!也可以理解为因为是选择子集,所以每个物品只能用一次

而m 和 n相当于是一个背包,并不是属于两个背包,只是一个2维度的背包

这里要注意,m和n是容量不是物品,也就意味着m和n代表的是背包。加上本质上选子集还是每个物品只能用一次,所以是01背包问题。

(理解成多重背包主要是把m和n混淆为物品了,感觉这是不同数量的物品,所以以为是多重背包。但是实际上多重背包是限制物品个数,而不是限制背包

本题01背包,背包有两个维度,一个是m 一个是n,而不同长度的字符串就是不同大小的待装物品

与之前01背包问题的区别

之前几道01背包问题,是给出容器容量,问装满容器的最大价值(价值=重量的时候就是最大重量)

是多少/能不能装满背包/背包尽量装最多能装多少/装满背包一共多少种方案

但是本题是01背包的两个维度,是求背包装满的时候最多有多少个物品

DP数组的含义

我们需要装满一个 容量为m个0,n个1的背包,问背包里最多有多少个物品。

背包有两个维度,所以我们需要定义一个二维DP数组,因为一维DP数组无法表现出背包的两个维度。

二维DP数组dp[i][j]表示,容量为i个0,j个1的背包,最多有dp[i][j]个物品。(也就是装满i个0,j个1的背包,最多有dp个物品

递推公式(也是求最大值)

01背包递推公式:

dp[j]=max(dp[j],dp[j-weight[i]]+value[i]);

本题的物品也就是str数组里面的元素,例如["10", "0001", "111001", "1", "0"]里的"0001"就是一个物品,这个物品的重量是x个0,y个1背包的最大重量是m个0,n个1

因此我们放入每个物品的状态,就是dp[i-x][j-y]

由于dp[i][j]表示的是容量为{i,j}的背包最多能放的物品个数,因此这个物品放进来之后,物品个数现在的状态是:dp[i-x][j-y]+1,意味着背包能放的容量减少,但是背包物品个数+1。

(DP数组数值本来代表的就是物品个数下标代表容量

我们要取的是物品个数的最大值,因此还需要和自身进行对比,存下来历史最大值。(和494.分割等和子集差不多,都是取最大)

因此本题递推公式为:

dp[i][j]=max(dp[i][j],dp[i-x][j-y]+1);//其中x是元素中0的个数,y是元素中1的个数(物品本身重量属性)

初始化

找最大值问题一般初始化都是0,但是要注意dp[0][0]的情况。

dp[0][0]是容量为{0,0}的时候,能装的物品个数就是0。非零下标也全部初始成0,防止求最大值过程被覆盖。

dp[i][j]表示物品个数,最小就是0)

遍历顺序

遍历顺序也是01背包的遍历顺序。

完整版

  • 注意二维背包内层for循环倒序遍历的方式二维背包的倒序遍历和一维背包倒序类似,但是都要注意下标越界的问题
  • 背包倒序遍历的for边界值问题,可以先都写成i>=0和j>=0,后面写完了递推公式再修改
class Solution {
public:
    int findMaxForm(vector<string>& strs, int m, int n) {
        //建立二维DP数组存放物品个数dp,下标m是0 n是1
        vector<vector<int>>dp(m+1,vector<int>(n+1,0));//二维数组,最开始手误写成了一维
        
        //对于strs里面每个数字,找重量属性,这已经属于遍历物品了
        for(int i=0;i<strs.size();i++){
            int zeroNum = 0;
        	int oneNum = 0;
            for(int j=0;j<strs[i].size();j++){//注意字符串本身就是一个数组,一维字符数组等于一个二维int数组
                if(strs[i][j]=='0') zeroNum++;
                else oneNum++;
            }
            //统计完物品的重量,再进行dp递推,物品已经在外层遍历,直接开始背包容量倒序遍历
            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];
    }
};

总结

01背包问题不同维度的应用:

  • 纯 0 - 1 背包 是求 给定背包容量,背包的最大价值是多少
    1. 分割等和子集 是求 给定背包容量,能不能装满这个背包
    1. 最后一块石头的重量 II 是求 给定背包容量,尽可能装,最多能装多少
    1. 目标和 是求 给定背包容量,装满背包一共有多少种方案
  • 474.一和零 是求 给定背包容量,装满背包最多有多少个物品(本题属于二维容量的背包)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/753004.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【数据结构】树与二叉树(上)

目录 前言&#xff1a; 一、树&#xff1a; 1.树的概念&#xff1a; 2.树的相关概念&#xff1a; 3.树的表示&#xff1a; 4.书的实际使用场景&#xff1a; 二、二叉树&#xff1a; 1.二叉树的概念&#xff1a; 2.两种特殊二叉树&#xff1a; ①.满二叉树&#xff1a;…

力扣每日一题2023.7.13

题目: 示例: 分析: 给我们一个矩阵,我们需要找出一条路径从矩阵第一层(索引为0)到达矩阵最后一层,并且使得路径上的数值之和最小. 如果是老手,那么应该一眼就能看出来可以使用动态规划,如果看不出来,那我们接下来一起分析分析. 首先我们先不要搞这么复杂,以示例1为例,我们就…

Redis数据结构 — QuickList

目录 quicklist 结构设计 总结 quicklist 结构设计 quicklistNode 结构体里包含了前一个节点和下一个节点指针&#xff0c;这样每个 quicklistNode 形成了一个双向链表。但是链表节点的元素不再是单纯保存元素值&#xff0c;而是保存了一个压缩列表&#xff0c;所以 quickli…

JSP基础

javaWeb项目目录 src&#xff1a;存放Java源文件 src/main/java/com&#xff1a;存放相应的Java代码&#xff0c;并根据对应的Java项目继续分层架构&#xff0c;主要有以下几个软件包。 bean包&#xff1a;封装类&#xff0c;一般是按照数据库的来写内容的&#xff0c;一个表…

Sentry 监控部署与使用(详细流程)

一、简介 Sentry 是一个开源的实时错误监控的项目&#xff0c;它支持很多端的配置&#xff0c;包括 web 前端、服务器端、移动端、游戏端。 基于 Django 构建的现代化的实时事件日志监控、记录和聚合平台&#xff0c;主要用于如何快速的发现故障。更快地解决错误和性能问题&…

vue——自定义指令,实现拖拽改变元素的宽度——技能提升

最近在看企业微信时&#xff0c;发现tapd的需求部分&#xff0c;分为左右两部分&#xff0c;左侧可以实现拖拽改变宽度。 感觉这样的实现效果比较好&#xff0c;再联想到之前写绩效结构时&#xff0c;也是同样的左右布局。 如果能实现同样的效果&#xff0c;则算是很好一种体…

【方法】公众号上传的视频不能横屏播放,如何解决?

目录 说明 解决步骤 步骤一&#xff1a;开启微信横屏模式 步骤二&#xff1a;打开手机自动旋转功能 说明 直接用手机打开公众号文章上内嵌的视频&#xff0c;发现只能横屏播放&#xff0c;无法全屏查看。 这个时候学习&#xff0c;尤其是看视频课程的时候无法看清楚全图。…

华为发布大模型时代AI存储新品

7月14日&#xff0c;华为发布大模型时代AI存储新品&#xff0c;为基础模型训练、行业模型训练&#xff0c;细分场景模型训练推理提供存储最优解&#xff0c;释放AI新动能。 企业在开发及实施大模型应用过程中&#xff0c;面临四大挑战&#xff1a; 首先&#xff0c;数据准备时…

数据结构:第五章 树

文章目录 一、树的基本概念1.1树的定义1.2树的基本用语1.2.1结点之间的关系描述1.2.2结点、树的属性描述1.2.3有序树、无序树1.2.4森林1.2.5小结 1.3树的性质 二、二叉树的概念2.1二叉树的定义和基本术语2.2二叉树的性质2.2.1二叉树常考性质2.2.2完全二叉树常考性质 2.3二叉树的…

使用chatgpt过funcaptcha验证码3个人学习记录

funcaptcha 验证码3 通过记录 往期验证码&#xff1a;http://t.csdn.cn/ulgXY funcaptcha1 往期验证码&#xff1a;http://t.csdn.cn/3xMnZ funcaptcha2 funcaptcha 那个公司开发的简要介绍&#xff1a; Funcaptcha是由hCaptcha公司开发的一种人机验证系统。hCaptcha是一家位…

快速排序的非递归实现、归并排序的递归和非递归实现、基数排序、排序算法的时间复杂度

文章目录 快速排序的非递归三数取中法选取key快速排序三路划分 归并排序的递归归并排序的非递归计数排序稳定性排序算法的时间复杂度 快速排序的非递归 我们使用一个栈来模拟函数的递归过程&#xff0c;这里就是在利用栈分区间。把一个区间分为 [left,keyi-1][key][keyi1,right…

机器学习(13)--支持向量机

目录 一、支持向量机概述 二、Sklearn中的SVM概述 三、线性SVM损失函数 四、sklearn中进行可视化 1、导入模块 2、实例化数据集&#xff0c;可视化 3、网格点制作 4、建立模型并绘制决策边界和超平面 5、常用接口 6、如果数据是环形呢&#xff1f; 五、核函数 1、…

emacs下相对行号的设置

全局设置 全局开启行号显示&#xff1a;global-display-line-numbers-mode t 并设置 display-line-numbers-type的样式: relative 相对 配置代码如下: (use-package emacs:ensure t:config (setq display-line-numbers-type relative) (global-display-line-numbers-mode t)…

校园跑腿小程序如何运营赚钱,方法其实很简单

校园跑腿小程序是一种以满足大学生的校园内外需求为主要目标的创业方式。下面将详细介绍校园跑腿小程序的运营方式&#xff0c;包括市场调研、产品设计、用户获取与留存、服务流程管理等方面。 市场调研&#xff1a; 在开始校园跑腿小程序的运营之前&#xff0c;进行充分的市…

2023年经典【自动化面试题】附答案

一、请描述一下自动化测试流程&#xff1f; 自动化测试流程一般可以分为以下七步&#xff1a; 编写自动化测试计划&#xff1b; 设计自动化测试用例&#xff1b; 编写自动化测试框架和脚本&#xff1b; 调试并维护脚本&#xff1b; 无人值守测试&#xff1b; 后期脚本维…

【C++从0到王者】第九站:String基本介绍及使用

文章目录 一、String的基本使用二、String构造相关的成员函数1.String构造函数2.String析构函数3.operator运算符重载4.String增删查改之增5. operator[]运算符重载 三、String迭代器1.迭代器介绍2.string中迭代器的作用3.迭代器跟容器结合4.反向迭代器5.const修饰的迭代器 四、…

华夏ERP在虚拟机Ubuntu上的安装(测试实例)

1.虚拟机软件VirtualBOX 7.0 2.Ubuntu 版本 3.宝塔面板安装 百度搜索宝塔面板&#xff0c;按官网提示进行安装。下面截图是官网示例。 if [ -f /usr/bin/curl ];then curl -sSO download.cnnbt.net/install_panel.sh;else wget -O install_panel.sh download.cnnbt.net/install…

python接口自动化(三十七)-封装与调用--读取excel 数据(详解)

简介 在进行软件接口测试或设计自动化测试框架时&#xff0c;一个不比可避免的过程就是: 参数化&#xff0c;在利用python进行自动化测试开发时&#xff0c;通常会使用excel来做数据管理&#xff0c;利用xlrd、xlwt开源包来读写excel。例如&#xff1a;当我们登录的账号有多个的…

报错400是什么怎么解决呢?

首先要了解400错误是什么错误&#xff1a; HTTP状态码400表示"错误请求"。它是一种客户端错误状态码&#xff0c;表示服务器无法理解请求的语法或参数。当服务器收到一个无效的请求时&#xff0c;通常会返回400错误码。这可能是由于请求中缺少必要的参数、参数格式错…

亚马逊买家号怎么留评

要在亚马逊上留下产品评价&#xff0c;需要买家号有留评权限才行。以下是留评论的步骤&#xff1a; 1、登录亚马逊账号&#xff1a;使用您的买家账号和密码登录到亚马逊的网站或移动应用程序。 2、找到购买的产品&#xff1a;在亚马逊的网站或应用程序中&#xff0c;找到您购…