DP:二维费用背包问题

文章目录

  • 🎵二维费用背包问题
    • 🎶引言
    • 🎶问题定义
    • 🎶动态规划思想
    • 🎶状态定义和状态转移方程
    • 🎶初始条件和边界情况
  • 🎵例题
    • 🎶1.一和零
    • 🎶2.盈利计划
  • 🎵总结

在这里插入图片描述

在这里插入图片描述

🎵二维费用背包问题

🎶引言

背包问题是算法中的经典问题之一,其变种繁多。本文将介绍二维费用背包问题及其解决方案。

🎶问题定义

二维费用背包问题可以描述为:给定 (N) 个物品,每个物品有两个费用和一个价值,在两种费用的限制下,如何选择物品使得总价值最大。

🎶动态规划思想

动态规划是解决背包问题的常用方法。通过定义合适的状态和状态转移方程,我们可以有效地解决二维费用背包问题。

🎶状态定义和状态转移方程

我们定义 dp[i][j][k] 表示前 i 个物品在费用1不超过 j 和费用2不超过 k 的情况下的最大价值。状态转移方程为:

d p [ i ] [ j ] [ k ] = max ⁡ ( d p [ i − 1 ] [ j ] [ k ] , d p [ i − 1 ] [ j − c o s t 1 [ i ] ] [ k − c o s t 2 [ i ] ] + v a l u e [ i ] ) dp[i][j][k] = \max(dp[i-1][j][k], dp[i-1][j-cost1[i]][k-cost2[i]] + value[i]) dp[i][j][k]=max(dp[i1][j][k],dp[i1][jcost1[i]][kcost2[i]]+value[i])

🎶初始条件和边界情况

初始条件为 dp[0][j][k] = 0,表示没有物品时的最大价值为 0。边界条件需要根据实际问题进行处理。

🎵例题

🎶1.一和零

题目:

在这里插入图片描述

样例输出和输入:

在这里插入图片描述

算法原理:
这道题就是让我们找子集的长度,这个子集满足:当中的0不大于m个,当中的1不大于n个,最后返回最大的子集的长度,所以我们首先想到的是二维费用背包问题,因为有两个限制,这里的背包的限制就是0和1的个数的限制,这里的物品其实就是每个字符串。
状态表示: d p [ i ] [ j ] [ k ] dp[i][j][k] dp[i][j][k]表示从前 i i i个物品中选择的所有组合中,满足0的个数不大于m,1的个数不大于n个的所有组合中子集长度最大的那个的长度。
状态转移方程:
在这里插入图片描述
这里的a和b代表的是当前i位置字符串中0和1分别的个数,所以我们在进行填表的时候应该遍历一下字符串,将当中的0和1分别记录一下,状态转移方程:

d p [ i ] [ j ] [ k ] = m a x ( d p [ i − 1 ] [ j ] [ k ] , d p [ i − 1 ] [ j − a ] [ k − b ] ) dp[i][j][k]=max(dp[i-1][j][k],dp[i-1][j-a][k-b]) dp[i][j][k]=max(dp[i1][j][k],dp[i1][ja][kb])

初始化:

代码:
未优化的代码:

class Solution {
public:int findMaxForm(vector<string>& strs, int m, int n){int sz = strs.size();vector<vector<vector<int>>> dp(sz + 1, vector<vector<int>>(m + 1, vector<int>(n + 1)));for (int i = 1;i <= sz;i++){//统计一下字符串中0和1的个数int a = 0, b = 0;for (auto e : strs[i - 1]){if (e == '1')b++;else a++;}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 - 1][j][k], dp[i - 1][j - a][k - b] + 1);}}}return dp[sz][m][n];}
};

滚动数组优化的代码:

class Solution {
public:int findMaxForm(vector<string>& strs, int m, int n){int sz = strs.size();vector<vector<int>> dp(m + 1, vector<int>(n + 1));for (int i = 1;i <= sz;i++){//统计一下字符串中0和1的个数int a = 0, b = 0;for (auto e : strs[i - 1]){if (e == '1')b++;else a++;}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];}
};

运行结果:
在这里插入图片描述

🎶2.盈利计划

题目:

在这里插入图片描述

样例输出和输入:

在这里插入图片描述

算法原理:
这道题每个group对应一个profit,下标是对应的。
在这里插入图片描述
根据上面的图片加上题目要求,我们可以得知,我们每次选择的利润必须大于给定的 m i n P r o f i t minProfit minProfit然后每次需要的人口不能超过 n n n,最后求出满足这个条件的所有组合有多少种。
状态表示: d p [ i ] [ j ] [ k ] dp[i][j][k] dp[i][j][k]表示从前i个工作计划中选择,人数不超过i的,但是盈利大于k的所有组合数的总和。
状态转移方程:
第一种状态:不选择i位置, d p [ i − 1 ] [ j ] [ k ] dp[i-1][j][k] dp[i1][j][k]

第二种状态:选择i位置,首先考虑二维 d p [ i − 1 ] [ j − g r o u p [ i ] ] dp[i-1][j-group[i]] dp[i1][jgroup[i]]这里我们考虑一下 j − g r o u p [ i ] ≤ 0 j-group[i]\leq0 jgroup[i]0是否成立将group[i]移到右边去可以得到: j ≤ g r o u p [ i ] j\leq group[i] jgroup[i]这个是什么意思呢?表示i工作需要的人口是大于总人口j的,所以这肯定是不可能的,所以这里中只能是 j − g r o u p [ i ] ≥ 0 j-group[i]\geq0 jgroup[i]0,我们再来考虑三维的: d p [ i − 1 ] [ j − g r o u p [ i ] ] [ k − p r o f i t [ i ] ] dp[i-1][j-group[i]][k-profit[i]] dp[i1][jgroup[i]][kprofit[i]]我们来考虑 k − p r o f i t [ i ] ≤ 0 k-profit[i]\leq0 kprofit[i]0是否成立,首先我们还是继续移一下项: k ≤ p r o f i t [ i ] k \leq profit[i] kprofit[i]这里k表示总的利润,profit表示当前工作产出的利润,所以这里的意思就表示无论前面总利润是多少,这里都都能满足当前的利润,所以我们只需要选择0即可,所以第二种状态:

d p [ i − 1 ] [ j − g r o u p [ i ] ] [ m a x ( 0 , k − p r o f i t [ i ] ) ] dp[i-1][j-group[i]][max(0,k-profit[i])] dp[i1][jgroup[i]][max(0,kprofit[i])]

最后这两种状态的总和就是当前状态的所有组合的总和:

d p [ i ] [ j ] [ k ] = d p [ i − 1 ] [ j ] [ k ] + d p [ i − 1 ] [ j − g r o u p [ i ] ] [ m a x ( 0 , k − p r o f i t [ i ] ) ] dp[i][j][k]=dp[i-1][j][k]+dp[i-1][j-group[i]][max(0,k-profit[i])] dp[i][j][k]=dp[i1][j][k]+dp[i1][jgroup[i]][max(0,kprofit[i])]

代码:
未优化的代码:

class Solution {
public:int profitableSchemes(int n, int minProfit, vector<int>& group, vector<int>& profit) {int len = group.size();int MOD = 1e9 + 7;vector<vector<vector<int>>> dp(len + 1, vector<vector<int>>(n + 1, vector<int>(minProfit + 1)));for (int j = 0;j <= n;j++){dp[0][j][0] = 1;}for (int i = 1;i <= len;i++){for (int j = 0;j <= n;j++){for (int k = 0;k <= minProfit;k++){dp[i][j][k] = dp[i - 1][j][k];if (j >= group[i-1])dp[i][j][k] += dp[i - 1][j - group[i - 1]][max(0, k - profit[i - 1])];dp[i][j][k] %= MOD;}}}return dp[len][n][minProfit];}
};

优化过后的代码:

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

运行结果:
在这里插入图片描述

🎵总结

通过本文的学习,我们了解了二维费用背包问题的基本概念和解决方法。与传统的单一费用背包问题不同,二维费用背包问题在解决时需要同时考虑两种费用的限制,这使得问题更具挑战性,但也更贴近实际应用场景。我们通过动态规划的方法,逐步构建状态转移方程,并利用二维数组来存储中间结果,从而实现了对问题的高效求解。

在实际应用中,掌握二维费用背包问题的解决思路,可以帮助我们在资源分配、投资组合等多方面优化决策。希望通过本次的学习,大家不仅能够掌握相关的算法技巧,还能够举一反三,灵活应用于更多复杂的优化问题中。

今后,我们将继续探讨更为复杂的动态规划问题,进一步提升算法设计和问题求解能力。谢谢大家的阅读,希望本文对你有所帮助。

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

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

相关文章

OpenAI突然停止中国API使用,出海SaaS产品如何化挑战为机遇?

2023年是AI爆发的年代&#xff0c;人工智能带来的信息裂变刷新了整个SaaS行业。在这个AI引领的时代&#xff0c;我们不应该单纯依赖工具本身&#xff0c;而是要理解如何将这些AI功能与行业相结合。 然而&#xff0c;上周OpenAI宣布禁止对中国提供API服务&#xff0c;有一些用户…

基于Transformer神经网络的锂离子电池剩余使用寿命估计MATLAB实现【NASA电池数据集】

Transformer神经网络 基于Transformer神经网络的锂离子电池剩余使用寿命估计是一种先进的方法&#xff0c;它利用了Transformer模型在处理序列数据方面的优势。 Transformer能够有效地捕捉时间序列中的长程依赖关系和非线性模式&#xff0c;相比传统的基于循环神经网络&…

【OnlyOffice】桌面应用编辑器,插件开发大赛,等你来挑战

OnlyOffice&#xff0c;桌面应用编辑器&#xff0c;最近版本已从8.0升级到了8.1 从PDF、Word、Excel、PPT等全面进行了升级。随着AI应用持续的火热&#xff0c;OnlyOffice也在不断推出AI相关插件。 因此&#xff0c;在此给大家推荐一下OnlyOffice本次的插件开发大赛。 详细信息…

WPF中Background=“{x:Null}“ 和 Transparent

WPF中关于背景透明和背景无 此时&#xff0c;我代码中是写的有有个控件&#xff0c;一个Border &#xff0c;一个TextBox &#xff0c;范围都是全屏这么大&#xff0c;可以输入TextBox 因为&#xff0c;当border没有设置背景的时候&#xff0c;实际上是&#xff1a; <Borde…

Python的招聘数据分析与可视化管理系统-计算机毕业设计源码55218

摘要 随着互联网的迅速发展&#xff0c;招聘数据在规模和复杂性上呈现爆炸式增长&#xff0c;对数据的深入分析和有效可视化成为招聘决策和招聘管理的重要手段。本论文旨在构建一个基于Python的招聘数据分析与可视化管理系统。 该平台以主流招聘平台为数据源&#xff0c;利用Py…

实战whisper第三天:fast whisper 语音识别服务器部署,可远程访问,可商业化部署(全部代码和详细部署步骤)

Fast Whisper 是对 OpenAI 的 Whisper 模型的一个优化版本,它旨在提高音频转录和语音识别任务的速度和效率。Whisper 是一种强大的多语言和多任务语音模型,可以用于语音识别、语音翻译和语音分类等任务。 Fast Whisper 的原理 Fast Whisper 是在原始 Whisper 模型的基础上进…

MySQL的count()方法慢

前言 mysql用count方法查全表数据&#xff0c;在不同的存储引擎里实现不同&#xff0c;myisam有专门字段记录全表的行数&#xff0c;直接读这个字段就好了。而innodb则需要一行行去算。 比如说&#xff0c;你有一张短信表(sms)&#xff0c;里面放了各种需要发送的短信信息。 …

SpringBoot新手快速入门系列教程二:MySql5.7.44的免安装版本下载和配置,以及简单的Mysql生存指令指南。

我们要如何选择MySql 目前主流的Mysql有5.0、8.0、9.0 主要区别 MySQL 5.0 发布年份&#xff1a;2005年特性&#xff1a; 基础事务支持存储过程、触发器、视图基础存储引擎&#xff08;如MyISAM、InnoDB&#xff09;外键支持基本的全文搜索性能和扩展性&#xff1a; 相对较…

3.python

闯关 3作业 本节关卡&#xff1a; 学习 python 虚拟环境的安装 Python 的基本语法 学会 vscode 远程连接 internstudio 打断点调试 python 程序

ctfshow web 36d 练手赛

不知所措.jpg 没啥用然后测试了网站可以使用php伪达到目的 ?filephp://filter/convert.base64-encode/resourcetest/../index.<?php error_reporting(0); $file$_GET[file]; $file$file.php; echo $file."<br />"; if(preg_match(/test/is,$file)){inclu…

火影短视频:成都柏煜文化传媒有限公司

火影短视频&#xff1a;忍术与情怀的闪回之旅 在浩瀚的动漫宇宙中&#xff0c;《火影忍者》无疑是一颗璀璨的明星&#xff0c;它以独特的忍者世界为背景&#xff0c;讲述了主人公漩涡鸣人从孤儿到忍界英雄的励志故事。随着短视频平台的兴起&#xff0c;成都柏煜文化传媒有限公…

98 - IDEA远程调试服务器Java程序

Java 提供了一套标准的调试协议&#xff08;JDWP - Java Debug Wire Protocol&#xff09;&#xff0c;允许调试器&#xff08;IDE&#xff09;与被调试程序&#xff08;应用&#xff09;之间进行通信。 1.服务器特定命令启动程序 在服务器上以以下命令启动Java程序 java -a…

优化路由,优化请求url

1、使用父子关系调整下使其更加整洁 2、比如说我修改了下url,那所有的页面都要更改 优化&#xff1a;把这个url抽出来&#xff0c;新建一个Api文件夹用于存放所有接口的url&#xff0c;在业务里只需要关注业务就可以 使用时 导包 发请求 如果想要更改路径&#xff0c;在这里…

竞赛选题 卷积神经网络手写字符识别 - 深度学习

文章目录 0 前言1 简介2 LeNet-5 模型的介绍2.1 结构解析2.2 C1层2.3 S2层S2层和C3层连接 2.4 F6与C5层 3 写数字识别算法模型的构建3.1 输入层设计3.2 激活函数的选取3.3 卷积层设计3.4 降采样层3.5 输出层设计 4 网络模型的总体结构5 部分实现代码6 在线手写识别7 最后 0 前言…

《第一行代码》小结

文章目录 一. Android总览1. 系统架构2. 开发环境3. 在红米手机上运行4. 项目资源详解4.1 整体结构4.2 res文件4.3 build.gradle文件 二. Activity0. 常用方法小结1. 创建一个Activity 一. Android总览 1. 系统架构 应用层&#xff1a;所有安装在手机上的应用程序 应用框架层&…

SQL-DCL(三)

一.DCL介绍 DCL英文全称是Data Control Language(数据库控制语言),用来管理数据库 用户,控制数据库的访问权限。 二.两个方面 1.数据库可以由那些用户访问 2.可以访问那些内容 三.DCL-管理用户 1.查询用户 USE mysql SELECT * FROM user 2.创建用户 CREATE USER…

女生学计算机好不好?感觉计算机分有点高……?

众所周知&#xff0c;在国内的高校里&#xff0c;计算机专业的女生是非常少的&#xff0c;很多小班30人左右&#xff0c;但是每个班女生人数只有个位数。这就给很多人一个感觉&#xff0c;是不是女生天生就不适合学这个东西呢&#xff1f;女生是不是也应该放弃呢&#xff1f;当…

【算法专题】双指针算法

1. 移动零 题目分析 对于这类数组分块的问题&#xff0c;我们应该首先想到用双指针的思路来进行处理&#xff0c;因为数组可以通过下标进行访问&#xff0c;所以说我们不用真的定义指针&#xff0c;用下标即可。比如本题就要求将数组划分为零区域和非零区域&#xff0c;我们不…

软件设计之Java入门视频(12)

软件设计之Java入门视频(12) 视频教程来自B站尚硅谷&#xff1a; 尚硅谷Java入门视频教程&#xff0c;宋红康java基础视频 相关文件资料&#xff08;百度网盘&#xff09; 提取密码&#xff1a;8op3 idea 下载可以关注 软件管家 公众号 学习内容&#xff1a; 该视频共分为1-7…

使用Python绘制堆积柱形图

使用Python绘制堆积柱形图 堆积柱形图效果代码 堆积柱形图 堆积柱形图&#xff08;Stacked Bar Chart&#xff09;是一种数据可视化图表&#xff0c;用于显示不同类别的数值在某一变量上的累积情况。每一个柱状条显示多个子类别的数值&#xff0c;子类别的数值在柱状条上堆积在…