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

文章目录

    • 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是1vector<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.hqwc.cn/news/21845.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

奥特曼与钢铁侠【InsCode Stable Diffusion美图活动一期】

文章目录 简介图片生成步骤更多体验方式 简介 InsCode 是一个一站式的软件开发服务平台&#xff0c;从开发-部署-运维-运营&#xff0c;都可以在 InsCode 轻松完成。 InsCode 的 Ins 是 Inspiration&#xff0c;意思是创作、寻找有灵感的代码。 Stable Diffusion是文图生成模型…

手机快充协议

高通:QC2.0、QC3.0、QC3.5、QC4.0、QC5.0、 FCP、SCP、AFC、SFCP、 MTKPE1.1/PE2.0/PE3.0、TYPEC、PD2.0、PD3.0/3.1、VOOC 支持 PD3.0/PD2.0 支持 QC3.0/QC2.0 支持 AFC 支持 FCP 支持 PE2.0/PE1.1 联发科的PE&#xff08;Pump Express&#xff09;/PE 支持 SFCP 在PP…

narak靶机详解

narak靶机复盘 首先对靶机进行扫描&#xff0c;找到靶机的真实ip地址。 然后dirb进行目录扫描&#xff0c;扫描到一个目录&#xff0c;我们打开发现是一个登陆界面。 并没有用户名和密码&#xff0c;我们就用cewl扫描这个网站&#xff0c;扫出一个字典&#xff0c;用来暴力破…

【微信小程序创作之路】- 小程序窗口整体配置(导航栏、标题)

【微信小程序创作之路】- 小程序窗口导航栏配置 第五章 微信小程序窗口导航栏配置 文章目录 【微信小程序创作之路】- 小程序窗口导航栏配置前言一、入口文件的配置二、页面配置三、全局默认窗口配置1.navigationBarTitleText&#xff1a;导航栏标题文字2.navigationBarBackgr…

Unity 限制范围-限制在4分之一圆柱形范围内活动

在我的游戏中&#xff0c;玩家的两只手操控中&#xff0c;不想让他们的手围着自己在一个圆形范围内随便乱跑&#xff0c;左手只想让他在左上角&#xff0c;右手在右上角范围活动。所以我制作这样一个算法来实现。 首先用Dot函数划分出4个区域&#xff0c;然后根据区域计算修正…

分配操作菜单

目录 概述介绍数据库后端前端效果展示 概述 在写后台管理系统时, 我们可以根据不同的登录人,给予不同的功能菜单 如 :给楼栋管理员登录时分配(楼栋管理,宿舍管理) 所以在数据库就要创建: 1.登录人与角色表, 2再给角色表分配操作菜单 登录时查询对应的操作菜单,将数据响应给前端…

记一次rabbitmq消息发送成功,消费丢失问题

记一次rabbitmq消息发送成功&#xff0c;消费丢失问题 背景 测试数据归档&#xff0c;偶现数据未归档 排查 idea线上调试&#xff0c;log日志&#xff0c;数据库消息发送记录&#xff0c;代码分块重复执行看哪块出的问题&#xff0c;结果均无问题&#xff0c;最后使用rabbi…

如何能够极速浏览大体积tif影像文件?

在无人机航拍的高清正射影像中&#xff0c;大体积文件是普遍现象&#xff0c;几十GB的TIFF文件很常见。常规的浏览方式特别容易导致卡顿&#xff0c;用户需要花费半天时间等待影像图的呈现。 建议您尝试将tiff格式快速转换为mbtiles或lrp格式&#xff0c;mbtiles和lrp格式专门…

UE编辑器灯光颜色,能量传入Shader流程

编辑器界面&#xff1a; 代码流程&#xff1a; FLinearColor ULightComponent::GetColoredLightBrightness() const {// Brightness in Lumensfloat LightBrightness ComputeLightBrightness();FLinearColor Energy FLinearColor(LightColor) * LightBrightness;if (bUseTem…

如何在Windows 8和10中检查最后一次的启动模式

Windows 8、Windows 8.1 和 Windows 10 中的用户可以在 PC 上执行混合关机(快速启动)、完全关机或休眠。 快速启动(又名:hiberboot、混合启动或混合关机)在 Windows 中默认打开,是一种帮助你的电脑在关机后更快启动的设置。甚至比休眠还要快。 休眠是一种主要为笔记本电…

推荐五款优秀,可替代商业软件的开源软件

​ 在日常的使用中&#xff0c;我们需要使用各种软件来提高我们的工作效率或者进行创意的表达。然而&#xff0c;商业软件价格昂贵&#xff0c;某些国产软件又充斥着广告。因此&#xff0c;开源软件成为了一个不错的选择&#xff0c;以下是我推荐的五款优秀的开源软件。 图片浏…

nginx配置IP白名单

1、添加IP白名单文件 在nginx目录的 conf 中添加文件 ip.conf&#xff0c;注意白名单文件不用添加任何注释&#xff0c;可以有空行 vi ip.conf 192.168.3.11 1;192.168.3.10 1; 192.168.0.112 1;2、配置nginx.conf 编辑http节点&#xff1a; http {# ...# geo IP whitelist…