当前位置: 首页 > news >正文

C++算法 —— 动态规划(10)二维费用背包

文章目录

  • 1、动规思路简介
  • 2、一和零
  • 3、盈利计划


背包问题需要读者先明白动态规划是什么,理解动规的思路,并不能给刚接触动规的人学习。所以最好是看了之前的动规博客,以及两个背包博客,或者你本人就已经懂得动规了。

1、动规思路简介

动规的思路有五个步骤,且最好画图来理解细节,不要怕麻烦。当你开始画图,仔细阅读题时,学习中的沉浸感就体验到了。

状态表示
状态转移方程
初始化
填表顺序
返回值

动规一般会先创建一个数组,名字为dp,这个数组也叫dp表。通过一些操作,把dp表填满,其中一个值就是答案。dp数组的每一个元素都表明一种状态,我们的第一步就是先确定状态。

状态的确定可能通过题目要求来得知,可能通过经验 + 题目要求来得知,可能在分析过程中,发现的重复子问题来确定状态。还有别的方法来确定状态,但都大同小异,明白了动规,这些思路也会随之产生。状态的确定就是打算让dp[i]表示什么,这是最重要的一步。状态表示通常用某个位置为结尾或者起点来确定。

状态转移方程,就是dp[i]等于什么,状态转移方程就是什么。像斐波那契数列,dp[i] = dp[i - 1] + dp[i - 2]。这是最难的一步。一开始,可能状态表示不正确,但不要紧,大胆制定状态,如果没法推出转移方程,没法得到结果,那这个状态表示就是错误的。所以状态表示和状态转移方程是相辅相成的,可以帮你检查自己的思路。

要确定方程,就从最近的一步来划分问题。

初始化,就是要填表,保证其不越界。像第一段所说,动规就是要填表。比如斐波那契数列,如果要填dp[1],那么我们可能需要dp[0]和dp[-1],这就出现越界了,所以为了防止越界,一开始就固定好前两个值,那么第三个值就是前两个值之和,也不会出现越界。初始化的方式不止这一点,有些问题,假使一个位置是由前面2个位置得到的,我们初始化最一开始两个位置,然后写代码,会发现不够高效,这时候就需要设置一个虚拟节点,一维数组的话就是在数组0位置处左边再填一个位置,整个dp数组的元素个数也+1,让原先的dp[0]变为现在的dp[1],二维数组则是要填一列和一行,设置好这一行一列的所有值,原先数组的第一列第一行就可以通过新填的来初始化,这个初始化方法在下面的题解中慢慢领会。

第二种初始化方法的注意事项就是如何初始化虚拟节点的数值来保证填表的结果是正确的,以及新表和旧表的映射关系的维护,也就是下标的变化。

填表顺序。填当前状态的时候,所需要的状态应当已经计算过了。还是斐波那契数列,填dp[4]的时候,dp[3]和dp[2]应当都已经计算好了,那么dp[4]也就出来了,此时的顺序就是从左到右。还有别的顺序,要依据前面的分析来决定。

返回值,要看题目要求。

背包问题有很多种分类,此篇是关于二维费用背包问题的,优化代码的方法在之前的两篇背包博客的模板题中,此篇就不写了。

2、一和零

474. 一和零

在这里插入图片描述

二维费用的背包问题就是原先的背包问题再加一个考虑因素,比如要考虑体积和重量。二维也有01和完全背包,这道题是二维01背包问题。

01背包中,dp[i][j]表示从前i个物品中挑选,总体积不超过j,最大价值的选法。这道题就要再加一维,变成dp[i][j][k],从前i个字符串中挑选,字符0的个数不超过j,字符1的个数不超过k,最大长度的选法。

状态转移方程。其实还是一样的分析。最后一个位置的字符串,如果不选i,那么就看dp[i - 1][j][k];如果选i,i这个字符串有a个0 1以及b个1,所以就看dp[i - 1][j - a][k - b],然后 + 1,并且要求j - a >= 0,k - b >= 0;两个值取max。

初始化时,i为0,则dp[0][j][k]全为0。返回值,因为要从整个字符串数组中挑选,而不是其中某一个最大值,所以返回值是最后一个值。

    int findMaxForm(vector<string>& strs, int m, int n) {int len = strs.size();vector<vector<vector<int>>> dp(len + 1, vector<vector<int>>(m + 1, vector<int>(n + 1)));for(int i = 1; i <= len; i++){int a = 0, b = 0;for(auto ch : strs[i - 1]){if(ch == '0') a++;else b++;}for(int j = 0; j <= m; j++){for(int k = 0; k <= n; k++){dp[i][j][k] = dp[i - 1][j][k];if(j >= a && k >= b)dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j - a][k - b] + 1);}}}return dp[len][m][n];}

但肯定不能这样写,做优化。去掉i这一维,j和k从大到小循环。

    int findMaxForm(vector<string>& strs, int m, int n) {int len = strs.size();vector<vector<int>> dp(m + 1, vector<int>(n + 1));for(int i = 1; i <= len; i++){int a = 0, b = 0;for(auto ch : strs[i - 1]){if(ch == '0') a++;else b++;}for(int j = m; j >= a; j--){for(int k = n; k >= b; k--){dp[j][k] = max(dp[j][k], dp[j - a][k - b] + 1);}}}return dp[m][n];}

3、盈利计划

879. 盈利计划

在这里插入图片描述
给了n和minProFit,group和profit数组,挑选几个人做某一份工作,人数不能超过n,并且利润,也就是profit数组里的被挑选的数,要>= minProFit,选group中第几个元素,利润就是profit数组中第几个元素。每个工作只能选一个,所以就是01背包问题。

让dp[i][j][k]表示从前i个工作中挑选,总人数不超过j,总利润至少为k,总共的选法。

状态转移方程。我们当然还是以最后一个位置i来分析。选择第i个工作,那就看dp[i - 1][j][k];如果选i,那么按照上一个题就是dp[i - 1][j - g[i]],k部分,由于是至少,思路就不一样,如果p[i]小于,那么就正常地看[k - p[i]]位置,如果p[i]大于k,就不能选择k - p[i]的位置了,因为数组下标不能为负数,所以这样写max(0, k - p[i]),如果p[i]更大,那么保证前面至少为0就行。然后这两个数相加。

初始化时dp[0][j][0] = 1。填表顺序要保证i从小到大即可。返回值是最后一个值。

    int profitableSchemes(int n, int m, vector<int>& g, vector<int>& p) {const int MOD = 1e9 + 7;int len = g.size();vector<vector<int>> dp(n + 1, vector<int>(m + 1));for(int j = 0; j <= n; j++) dp[j][0] = 1;for(int i = 1; i <= len; i++){for(int j = n; j >= g[i - 1]; j--){for(int k = m; k >= 0; k--){dp[j][k] += dp[j - g[i - 1]][max(0, k - p[i - 1])];dp[j][k] %= MOD;}}}return dp[n][m];}

结束。

相关文章:

C++算法 —— 动态规划(10)二维费用背包

文章目录 1、动规思路简介2、一和零3、盈利计划 背包问题需要读者先明白动态规划是什么&#xff0c;理解动规的思路&#xff0c;并不能给刚接触动规的人学习。所以最好是看了之前的动规博客&#xff0c;以及两个背包博客&#xff0c;或者你本人就已经懂得动规了。 1、动规思路简…...

MySQL数据库正在耗用大量CPU的问题排查

这是一篇实战性的文章&#xff0c;如何处理正在发生的MYSQL服务器CPU飙升的问题&#xff0c;一般情况下&#xff0c;MySQL是不会耗用这么高的CPU的&#xff0c;要么是不走索引的查询&#xff0c;要么是同一时间出现了大量比较耗用资源的查询&#xff0c;不管出现的是哪一种情况…...

php替换字符串里的a变为b

$tempstrstr_replace("\\","/",$tempstr); //把$tempstr中的a替换成b $tempstrstr_replace("a","b",$tempstr);...

黑豹程序员-架构师学习路线图-百科:CSS-网页三剑客

文章目录 1、为什么需要CSS2、发展历史3、什么是CSS4、什么是SASS、SCSS 1、为什么需要CSS 作为网页三剑客的第二&#xff0c;CSS为何需要它&#xff0c;非常简单HTML只能完成页面的展现&#xff0c;但其做出来的页面奇丑无比。 随着网络的普及&#xff0c;人们的要求更高&…...

NUWA论文阅读

论文链接&#xff1a;NUWA: Visual Synthesis Pre-training for Neural visUal World creAtion 文章目录 摘要引言相关工作视觉自回归模型视觉稀疏自注意 方法3D数据表征3D Nearby Self-Attention3D编码器-解码器训练目标 实验实现细节与SOTA比较T2I微调T2V微调V2V微调Sketch-t…...

4.Tensors For Beginners-Vector Definition

在上一节&#xff0c;已经了解了前向和后向转换。 什么是向量&#xff1f; 定义1&#xff1a;向量是一个数字列表 这很简洁&#xff0c;也通俗易懂。 现有两个向量&#xff1a; 如果要把这两个向量给加起来&#xff0c;只需把对应位置的元素(组件)给加起来。 而要缩放向量&…...

vertx学习总结5

这章我们讲回调&#xff0c;英文名&#xff1a;Beyond callbacks 一、章节覆盖&#xff1a; 回调函数及其限制&#xff0c;如网关/边缘服务示例所示 未来和承诺——链接异步操作的简单模型 响应式扩展——一个更强大的模型&#xff0c;特别适合组合异步事件流 Kotlin协程——…...

Go,从命名开始!Go的关键字和标识符全列表手册和代码示例!

目录 一、Go的关键字列表和分类介绍关键字在Go中的定位语言的基石简洁与高效可扩展性和灵活性 关键字分类声明各种代码元素组合类型的字面表示基本流程控制语法协程和延迟函数调用 二、Go的关键字全代码示例关键字全代码示例 三、Go的标识符定义基础定义特殊规定关键字与标识符…...

【网络】网络扫盲篇 ——用简单语言和图解带你入门网络

网络的一些名词和基础知识讲解 前言正式开始一些基础知识发展背景运营商和生产商 协议协议的分层TCP/IP五层(或四层)模型&#xff08;可以不看&#xff0c;对新手来说太痛苦了&#xff0c;我这里只是为了让屏幕前的你过一遍就好&#xff0c;里面很多概念新手是不太懂的&#xf…...

【项目开发 | C语言项目 | C语言薪资管理系统】

本项目是一个简单的薪资管理系统&#xff0c;旨在为用户提供方便的员工薪资管理功能&#xff0c;如添加、查询、修改、删除员工薪资信息等。系统通过命令行交互界面与用户进行交互&#xff0c;并使用 txt 文件存储员工数据。 一&#xff0c;开发环境需求 操作系统&#xff1a;w…...

Android---GC回收机制与分代回收策略

目录 GC 回收机制 垃圾回收(Garbage Collection, GC) 垃圾回收算法 JVM 分代回收策略 1. 新生代 2. 老年代 GC Log 分析 引用 GC 回收机制 垃圾回收(Garbage Collection, GC) 垃圾就是内存中已经没有用的对象&#xff0c;JVM 中的垃圾回收器(Garbage Collector)会自…...

前缀、中缀、后缀表达式相互转换工具

目录 1. 界面一览 2. 使用说明 3. 实例演示 3.1 输入中缀 3.2 输入前缀 3.3 输入后缀 3.4 选择错误的类型 4. 代码 5. 资源地址 关于什么是前缀、中缀、后缀表达式&#xff0c;相信你不知道这个东西&#xff0c;那你也不会点进来这篇博客&#xff0c;当然&#xff0c;…...

Vue之ElementUI之动态树+数据表格+分页(项目功能)

目录 前言 一、实现动态树形菜单 1. 配置相应路径 2. 创建组件 3. 配置组件与路由的关系 index.js 4. 编写动态树形菜单 5. 页面效果演示 二、实现数据表格绑定及分页功能 1. 配置相应路径 2. 编写数据表格显示及分页功能代码 BookList.vue 3. 演示效果 总结 前言…...

【CAD二次开发】给CAD添加TRUSTEDPATHS避免dll插件信任弹窗

找到配置文件目录,遍历下面的每个配置文件; 找到 Variables 下的TRUSTEDPATHS项目;在后面添加新的目录即可,多个目录使用分号分隔; public static void AddPath(string trusedPath){// 指定注册表键的路径...

编译和链接

编译和链接 一&#xff1a;&#xff1f;&#xff1f;&#xff1f;二&#xff1a;翻译环境1&#xff1a;编译1&#xff1a;预处理2&#xff1a;编译 2&#xff1a;链接 三&#xff1a;运行环境&#xff1a; 本文章所使用的图片均来在yyds鹏哥一&#xff1a;&#xff1f;&#xf…...

常识判断 --- 科技常识

目录 力与热 光和声 航空成就 垃圾分类 百科知识 血型 二十四节气歌 春雨惊春清谷天 夏满忙夏暑相连 秋处露秋寒霜降 冬雪雪冬小大寒 力与热 光和声 航空成就 垃圾分类 百科知识 血型...

修改npm全局安装的插件(下载目录指向)

我们先打开终端 然后执行 npm config get prefix查看npm 的下载地址 一般都会在C盘 但是 我们都知道 C盘下东西多了是很不好的 所以 我们可以执行 npm config set prefix “E:\npmfile”将 npm 的下载地址 改变成 E盘下的 npmfile目录 这样 以后 默认全局安装的插件就会都到…...

<C++> 异常

C语言传统的处理错误的方式 传统的错误处理机制&#xff1a; 终止程序&#xff0c;如assert&#xff0c;缺陷&#xff1a;用户难以接受。如发生内存错误&#xff0c;除0错误时就会终止程序。返回错误码&#xff0c;缺陷&#xff1a;需要程序员自己去查找对应的错误。如系统的…...

聊聊HttpClientBuilder

序 本文主要研究一下HttpClientBuilder HttpClientBuilder httpclient-4.5.10-sources.jar!/org/apache/http/impl/client/HttpClientBuilder.java public class HttpClientBuilder {public static HttpClientBuilder create() {return new HttpClientBuilder();}protected…...

MacOS - Sonoma更新了啥

1 系统介绍 苹果公司于2023年9月26日发布了macOS Sonoma 14.0正式版。名称由来不知道&#xff0c;可能是地名&#xff1a;Sonoma是一个地名,指加利福尼亚州北部索诺玛县(Sonoma County)。 2 系统重要更新 2.1 将小组件添加到桌面 速览提醒事项和临近日程等。按住Control键点…...

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...

CSS设置元素的宽度根据其内容自动调整

width: fit-content 是 CSS 中的一个属性值&#xff0c;用于设置元素的宽度根据其内容自动调整&#xff0c;确保宽度刚好容纳内容而不会超出。 效果对比 默认情况&#xff08;width: auto&#xff09;&#xff1a; 块级元素&#xff08;如 <div>&#xff09;会占满父容器…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题

分区配置 (ptab.json) img 属性介绍&#xff1a; img 属性指定分区存放的 image 名称&#xff0c;指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件&#xff0c;则以 proj_name:binary_name 格式指定文件名&#xff0c; proj_name 为工程 名&…...

JVM 内存结构 详解

内存结构 运行时数据区&#xff1a; Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器&#xff1a; ​ 线程私有&#xff0c;程序控制流的指示器&#xff0c;分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 ​ 每个线程都有一个程序计数…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf

FTP 客服管理系统 实现kefu123登录&#xff0c;不允许匿名访问&#xff0c;kefu只能访问/data/kefu目录&#xff0c;不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...

排序算法总结(C++)

目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指&#xff1a;同样大小的样本 **&#xff08;同样大小的数据&#xff09;**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...

三分算法与DeepSeek辅助证明是单峰函数

前置 单峰函数有唯一的最大值&#xff0c;最大值左侧的数值严格单调递增&#xff0c;最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值&#xff0c;最小值左侧的数值严格单调递减&#xff0c;最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...

计算机基础知识解析:从应用到架构的全面拆解

目录 前言 1、 计算机的应用领域&#xff1a;无处不在的数字助手 2、 计算机的进化史&#xff1a;从算盘到量子计算 3、计算机的分类&#xff1a;不止 “台式机和笔记本” 4、计算机的组件&#xff1a;硬件与软件的协同 4.1 硬件&#xff1a;五大核心部件 4.2 软件&#…...

探索Selenium:自动化测试的神奇钥匙

目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...

c++第七天 继承与派生2

这一篇文章主要内容是 派生类构造函数与析构函数 在派生类中重写基类成员 以及多继承 第一部分&#xff1a;派生类构造函数与析构函数 当创建一个派生类对象时&#xff0c;基类成员是如何初始化的&#xff1f; 1.当派生类对象创建的时候&#xff0c;基类成员的初始化顺序 …...