01背包之---应用篇

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、01背包之---背包是否能被装满?
    • 例题1.
    • 分析题意
    • 例题2.
    • 分析题意
  • 二、01背包之---装满背包有多少种组合?
    • 例题1.
    • 分析题意
  • 三、01背包之---容量为N的背包最多可以装多少物品?
    • 例题1.
    • 分析题意
  • 总结


前言

上文我们讲完了01背包的一维的写法,了解了01背包问题的模型,就是每个物品可以被拿一次,求在有限的背包容量下,所能取得的最大价值是多少,但在刷题过程中题目往往不是直接给你一个这样的模板然后让你去求,所以我们今天来讲三种明面上不是背包问题的题目但其实就是01背包的题目
下面例题解答我们统一用一维dp解答,不仅代码比二维简洁,而且复杂度更低


一、01背包之—背包是否能被装满?

例题1.

在这里插入图片描述

分析题意

首先这道题要我们把一个数组分成两个数组,两个数组的和相同
首先这两个数组的各自总和ans肯定为总数组的和sum/2
那么如果这个原数组的和sum为奇数,肯定就不能分成功,这个我们现在可以单独判出来

其次我们仔细想一下,我们现在已知什么? 我们知道原数组总和sum
那是不是也知道了要分成两个数组,每个数组的和为 sum/2
是不是问题就转换为求背包容量为sum/2的一个背包,从原数组中选商品,看能不能正好装满这个背包
我们直接求背包容量为sum/2所能装的最大价值即可,如果装的最大价值就等于sum/2,那意思是不是就是可以装满这个背包,从而可以成功分为两个数组呢?

那么接下来我们直接上代码

class Solution {
public:bool canPartition(vector<int>& nums) {int sum=0;for(int i=0;i<nums.size();i++)sum+=nums[i];//求数组总和int dp[10001];//初始化for(int i=0;i<10001;i++)dp[i]=0;if(sum%2==1)return false;int target=sum/2;for(int i=0;i<nums.size();i++)//遍历物品{for(int j=target;j>=nums[i];j--){dp[j]=max(dp[j],dp[j-nums[i]]+nums[i]);}}if(dp[target]==target)return true;return false;}
};

在这里插入图片描述
关于dp数组的初始化以及遍历问题,请回顾上篇文章,这里不再过多讲解

例题2.

在这里插入图片描述

分析题意

这道题其实更第一题很类似
大家可以发现,其实也是分成两个数组,然后使两个数组的差最小,大家仔细想想,是不是这个道理?
我们直接上代码

class Solution {
public:int lastStoneWeightII(vector<int>& stones) {int sum=0;for(int i=0;i<stones.size();i++)sum+=stones[i];//计算总和int dp[10001];for(int i=0;i<10001;i++)dp[i]=0;//初始化int target=sum/2;for(int i=0;i<stones.size();i++){for(int j=target;j>=stones[i];j--){dp[j]=max(dp[j],dp[j-stones[i]]+stones[i]);}}if(2*dp[target]==sum)return 0;return sum-2*dp[target];}
};

在这里插入图片描述

二、01背包之—装满背包有多少种组合?

例题1.

在这里插入图片描述

分析题意

刚看到题目的时候我也一脸懵逼,后来发现,这就是排列组合的题目,我们可以把原数组分成两块,一方存储加号的元素,一方存储减号的元素,我们只需要找到有多少种组合的和满足与其中一方的和就行了,我们这里以加号的元素为准

假设所有+号的元素的总和为x 所有-号的元素的总和为y 原数组总和为sum 目标值为target
那么 x+y=sum
x-y=target

所以 x=(target+sum)/2
所以我们只需要找到装满容量为x的背包 有多少种组合即可
但这里有个注意点,这个 (target+sum)/2一定可以被整除嘛??
答案是一定的,不然凑不出结果,大家可以在草稿纸上写一下

所以我们现在有了dp数组
dp[j]表示容量为j的背包 装满后有多少种组合

那么递推公式呢?
dp[j]+=dp[j-nums[i]]
为什么呢?
大家可以想一下
dp[5]一定由dp[1]+dp[2]+dp[3]+dp[4]相加而来,那么为什么呢
比如我此时dp[1]=1,表示装满容量为1的背包有1种方式,那么此时我如果再装一个4的物品,是不是直接满容量了,所以dp[5]可以从dp[1]得来,同理可得dp[5]=dp[1]+dp[2]+dp[3]+dp[4]

class Solution {
public:int findTargetSumWays(vector<int>& nums, int target) {int sum=0;for(int i=0;i<nums.size();i++)sum+=nums[i];//计算总和int jiafa=(target+sum)/2;if(abs(target)>sum||(target+sum)%2==1)return 0;//无法构造出//装满容量为i的背包有dp[i]种组合int dp[10001];for(int i=1;i<10001;i++)dp[i]=0;dp[0]=1;for(int i=0;i<nums.size();i++){for(int j=jiafa;j>=nums[i];j--){dp[j]+=dp[j-nums[i]];}}return dp[jiafa];}
};

三、01背包之—容量为N的背包最多可以装多少物品?

例题1.

在这里插入图片描述

分析题意

我们仔细分析题目,我们可以把m个0 n个1当成背包容量,大家想一想是不是这样
我们最初一开始讲的01背包问题的时候,只有一个背包容量,然后求在这个容量的情况下,所能装的最大物品价值为多少,当时我们写的是一维的dp[j] 只有一个容量j 那这里我们是不是相当于有两个容量 m和ndp[m][n]表示在有m个0和n个1的情况下 所能装的最多的字符串个数为dp[m][n]个

此时我们注意!!!我们这虽然开的是二维的dp[m][n],但这两个变量都代表背包容量,相当于01背包中的dp[j],如果讲01背包问题写成二维的dp[i][j],那么我们这里就要写成dp[i][m][n]三维表示,因为i表示的是物品,后面两个都是背包容量,大家不要搞混

一维的递推公式维dp[j]=max(dp[j],dp[j-weight[i]]+value[i])
其实我们通过对比很快就能发现此题的递推公式为 dp[m][n]=max(dp[m][n],dp[m-weight[i]][n-weight[i]]+1) 这两个的意思都是要么不拿此物品 要么拿

class Solution {
public:int findMaxForm(vector<string>& strs, int m, int n) {int dp[m+5][n+5];//容量为m和n的背包能装多少个物品for(int i=0;i<m+2;i++){for(int j=0;j<n+2;j++){dp[i][j]=0;}}dp[0][0]=0;//求dp[m][n];//m个0 n个1for(int i=0;i<strs.size();i++)//遍历物品{int x=0;//记录有多少个0int y=0;//记录有多少个yfor(int k=0;k<strs[i].size();k++){if(strs[i][k]=='0')x++;else{y++;}}//遍历背包for(int j1=m;j1>=x;j1--){for(int j2=n;j2>=y;j2--){dp[j1][j2]=max(dp[j1][j2],dp[j1-x][j2-y]+1);}}}return dp[m][n];}
};

在这里插入图片描述

总结

今天讨论了01背包问题的背包是否能被装满装满背包有多少种组合的问题容量为N的背包最多可以装多少物品我们都是用一维来写,这样复杂度更低,判断背包是否能被装满,直接判断背包最大容量时可以装多少价值即可,如果和背包容量相等,就是装满了,在讨论装满背包有多少种组合的问题的时候,我们用递推公式 dp[j]+=dp[j-nums[i]] 即可
当判断一定容量的背包能装多少个的时候,在dp递推的时候里面把加value[i]改成+1即可,因为要求的不是最大价值,而是最多的数量

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

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

相关文章

DeepSeek赋能智慧文旅:新一代解决方案,重构文旅发展的底层逻辑

DeepSeek作为一款前沿的人工智能大模型&#xff0c;凭借其强大的多模态理解、知识推理和内容生成能力&#xff0c;正在重构文旅产业的发展逻辑&#xff0c;推动行业从传统的经验驱动向数据驱动、从人力密集型向智能协同型转变。 一、智能服务重构&#xff1a;打造全域感知的智…

uniapp修改picker-view样式

解决问题&#xff1a; 1.选中文案样式&#xff0c;比如字体颜色 2.修改分割线颜色 3.多列时&#xff0c;修改两边间距让其平分 展示效果&#xff1a; 代码如下 <template><u-popup :show"showPicker" :safeAreaInsetBottom"false" close&quo…

开源嵌入式实时操作系统uC/OS-II介绍

一、uC/OS-II的诞生&#xff1a;从开源实验到行业标杆 背景与起源 uC/OS-II&#xff08;Micro-Controller Operating System Version II&#xff09;诞生于1992年&#xff0c;由嵌入式系统先驱Jean J. Labrosse开发。其前身uC/OS&#xff08;1991年&#xff09;最初作为教学工…

8.spring对logback的支持

文章目录 一、入口二、源码解析LoggingApplicationListener 三、其它支持四、总结 本节以logback为背景介绍的 一、入口 gav: org.springframework.boot:spring-boot:3.3.4 spring.factories文件中有如下两个配置 org.springframework.boot.logging.LoggingSystemFactory\ …

OpenHarmony分布式数据管理子系统

OpenHarmony分布式数据管理子系统 简介 目录 组件说明 分布式数据对象数据共享分布式数据服务Key-Value数据库首选项关系型数据库标准数据化通路 相关仓 简介 子系统介绍 分布式数据管理子系统支持单设备的各种结构化数据的持久化&#xff0c;以及跨设备之间数据的同步、…

智慧后勤的消防管理:豪越科技为安全护航

智慧后勤消防管理难题大揭秘&#xff01; 在智慧后勤发展得如火如荼的当下&#xff0c;消防管理却暗藏诸多难题。传统模式下&#xff0c;消防设施分布得那叫一个散&#xff0c;就像一盘散沙&#xff0c;管理起来超费劲。人工巡检不仅效率低&#xff0c;还容易遗漏&#xff0c;不…

python轻量级框架-flask

flask简述 Flask 是 Python 生态圈中一个基于 Python 的Web 框架。其轻量、模块化和易于扩展的特点导致其被广泛使用&#xff0c;适合快速开发 Web 应用以及构建小型到中型项目。它提供了开发 Web 应用最基础的工具和组件。之所以称为微框架&#xff0c;是因为它与一些大型 We…

政安晨【零基础玩转各类开源AI项目】DeepSeek 多模态大模型Janus-Pro-7B,本地部署!支持图像识别和图像生成

政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff01; 目录 下载项目 创建虚拟环境 安装项目依赖 安装 Gradio&#xff08;UI&#xff09; 运…

在 Mac mini M2 上本地部署 DeepSeek-R1:14B:使用 Ollama 和 Chatbox 的完整指南

随着人工智能技术的飞速发展&#xff0c;本地部署大型语言模型&#xff08;LLM&#xff09;已成为许多技术爱好者的热门选择。本地部署不仅能够保护隐私&#xff0c;还能提供更灵活的使用体验。本文将详细介绍如何在 Mac mini M2&#xff08;24GB 内存&#xff09;上部署 DeepS…

【Godot4.3】基于绘图函数的矢量蒙版效果与UV换算

概述 在设计圆角容器时突发奇想&#xff1a; 将圆角矩形的每个顶点坐标除以对应圆角矩形所在Rect2的size&#xff0c;就得到了顶点对应的UV坐标。然后使用draw_colored_polygon&#xff0c;便可以做到用图片填充圆角矩形的效果。而且这种计算的效果就是图片随着其填充的图像缩…

51单片机-AT24CXX存储器工作原理

1、AT24CXX存储器工作原理 1.1、特点&#xff1a; 与400KHz&#xff0c;I2C总线兼容1.8到6.0伏工作电压范围低功耗CMOS技术写保护功能当WP为高电平时进入写保护状态页写缓冲器自定时擦写周期100万次编程/擦除周期可保存数据100年8脚DIP SOIC或TSSOP封装温度范围商业级和工业级…

Linux网络 网络层

IP 协议 协议头格式 4 位版本号(version): 指定 IP 协议的版本, 对于 IPv4 来说, 就是 4. 4 位头部长度(header length): IP 头部的长度是多少个 32bit, 也就是 4 字节&#xff0c;4bit 表示最大的数字是 15, 因此 IP 头部最大长度是 60 字节. 8 位服务类型(Type Of Service):…

Unity百游修炼(1)——FootBall详细制作全流程

一、引言 游玩测试&#xff1a; Football 游玩测试 1.项目背景与动机 背景&#xff1a;在学习 Unity 的过程中&#xff0c;希望通过实际项目来巩固所学知识&#xff0c;同时出于对休闲小游戏的喜爱&#xff0c;决定开发一款简单有趣的小游戏加深自己的所学知识点。 动机&#…

C语言(13)------------>do-while循环

1.do-while循环的语法 我们知道C语言有三大结构&#xff0c;顺序、选择、循环。我们可以使用while循环、for循环、do-while循环实现循环结构。之前的博客中提及到了前两者的技术实现。可以参考&#xff1a; C语言&#xff08;11&#xff09;-------------&#xff1e;while循…

【1】VS Code 新建上位机项目---C#基础语法

VS Code 新建上位机项目---C#基础语法 1 基本概念1.1 准备工具1.2 新建项目2 C#编程基础2.1 命名空间和类2.2 数据类型2.3 控制台输入输出2.3.1 输入输出: write 与 read2.3.2 格式化 : string.Foramt() 与 $2.3.3 赋值与运算2.4 类型转换2.4.1 数值类型之间的转换:(int)2.4…

SQL:DQL数据查询语言以及系统函数(oracle)

SQL Structured Query Language&#xff0c;结构化查询语言, 是一种用于管理和操作关系数据库的标准编程语言。 sql的分类 DQL&#xff08;Data Query Language&#xff09;&#xff1a;数据查询语言 DDL&#xff08;Data Definition Language&#xff09;&#xff1a;数据…

从单片机的启动说起一个单片机到点灯发生了什么下——使用GPIO点一个灯

目录 前言 HAL库对GPIO的抽象 核心分析&#xff1a;HAL_GPIO_Init 前言 我们终于到达了熟悉的地方&#xff0c;对GPIO的初始化。经过漫长的铺垫&#xff0c;我们终于历经千辛万苦&#xff0c;来到了这里。关于GPIO的八种模式等更加详细的细节&#xff0c;由于只是点个灯&am…

提效10倍:基于Paimon+Dolphin湖仓一体新架构在阿里妈妈品牌业务探索实践

1. 业务背景 阿里妈妈品牌广告数据包括投放引擎、下发、曝光、点击等日志&#xff0c;面向运筹调控、算法特征、分析报表、诊断监控等应用场景&#xff0c;进行了品牌数仓能力建设。随着业务发展&#xff0c;基于Lambda架构的数仓开发模式&#xff0c;缺陷日益突出&#xff1a;…

一文详解U盘启动UEFI/Legacy方式以及GPT/MBR关系

对于装系统的老手而说一直想研究一下装系统的原理&#xff0c;以及面对一些问题时的解决思路&#xff0c;故对以前的方法进行原理上的解释&#xff0c;主要想理解其底层原理。 引导模式 MBR分区可以同时支持UEFI和Legacy引导&#xff0c;我们可以看一下微pe制作的启动盘&#…

基于Docker的前端环境管理:从开发环境到生产部署的实现方案

# 基于Docker的前端环境管理&#xff1a;从开发环境到生产部署的实现方案 简介及前端开发环境挑战 简介 是一种容器化平台&#xff0c;可以将应用程序及其依赖项打包为一个容器&#xff0c;提供一种轻量级、可移植的环境。它能够简化开发、部署和运维的流程&#xff0c;提高…