多重背包问题

文章目录

  • 朴素算法
    • 基本思想
      • 代码
  • 二进制优化算法
    • 基本思想
      • 代码
  • 单调队列优化多重背包
    • 基本思想
      • 代码

在这里插入图片描述
多重背包我们其实可以看成为01背包和完全背包的组合。也可以把多重背包问题只转换成01背包问题,我们一起来看看解题思路。

朴素算法

基本思想

比如第i件物品有s个,我可以把相同种类的物品的进行合并,比如我拿出两件合并出一个新的物品,我拿出三件合并出一个新的物品,以此类推,我拿出s个合并出一个新的物品。基于这种思想,我们把第i件的s个物品转换为s种体积各不相同的物品,然后在用01背包的思想,求出最优解!

代码

#include<bits/stdc++.h>
using namespace std;
int v[110],w[110],s[110],m,n,f[110];
int main()
{cin>>m>>n;for(int i=1;i<=m;i++)cin>>v[i]>>w[i]>>s[i];for(int i=1;i<=m;i++){for(int j=n;j>=1;j--){for(int k=0;k<=s[i]&&k*v[i]<=j;k++){f[j]=max(f[j],f[j-k*v[i]]+k*w[i]);}}}cout<<f[n]<<endl;return 0;
}

二进制优化算法

基本思想

大家看到名字可能心声疑惑,二进制怎么优化呢?,其实只是借助二进制思想优化朴素解法,在朴素解法中我们需要把,每一种背包i,按个数1~s,分为不同类,形成新体积的种类,这种做法虽然剪枝优化过(k*v<=j)复杂度仍然很高,问题的关键在于怎么分,我们可不可以,在分的时候换一种算法,不再是从1分到s,并且也可以表示出,1到s,产生同样的效果!答案肯定是有的,就是用二进制思想优化,我们下面讲解这种思想。

举例,有1000个苹果,11个箱子,将1000个苹果放入11个箱子中。我想拿走n个苹果!

请问,如何放,才能保证我只拿走m个箱子,就可以带走这n个苹果呢?

解:第一个箱子放2^0,个,第二个放2的1次幂个,第三个放2的2次幂个,以此类推第11个箱子,最多能放2的10次幂,即1024个,但肯定没有那么多,所以我将剩下的苹果放在第10个箱子中。
比如我要拿出 5个苹果,我只需要拿走第1个和第3个箱子,
再比如,我要拿走10个苹果,我只需要拿走,第4个和第2个即可!

通过这种思想我们可以知道,任意的1~n的整数,我都可以通过二进制的思想,表示出来。

原理:
一个数字,我们可以按照二进制来分解为1 + 2 + 4 + 8 …… +2^n + 余数

十进制数字7,可以从二进制100,010,001做加和得到即111,001为1,010为2,100为4,也就是1、2、4,用1、2、4可以表示1~7中任意一个数。
再比如,10,可以分为1,2,4,3这个三是怎么来的呢? 3就是余数!

通过上述原理,我们可以把第i件物品的s件,按二进制思想分为1,2,4…到剩余。这样从复杂度为s,降到了(log2S)。最后的复杂度为O(V*Σlog n[i]),这样就快了许多!

代码

#include<bits/stdc++.h>
using namespace std;
int vv[12100],ww[12100],m,n,v,w,s,cnt=0,f[12100];
int main()
{cin>>m>>n;for(int i=1;i<=m;i++){cin>>v>>w>>s;for(int j=1;j<=s;j*=2){vv[++cnt]=v*j;ww[cnt]=w*j;s-=j;}if(s>0){vv[++cnt]=v*s;ww[cnt]=w*s;}}for(int i=1;i<=cnt;i++){for(int j=n;j>=vv[i];j--){f[j]=max(f[j],f[j-vv[i]]+ww[i]);}}cout<<f[n]<<endl;return 0;
}

单调队列优化多重背包

基本思想

首先要学习这个方法,大家一定需要学会单调队列,以及单调队列滑动窗口问题,这里我把我写的单调队列滑动窗口问题链接黏贴给大家,大家一定一定一定要先理解单调队列滑动窗口,不然后面很难跟上!

我通过朴素解法,添加了打印语句,将每一次的f数组的更新过程记录下来!

 f[j]=max(f[j],f[j-k*v]+k*w);//打印语句
printf("f[%d]=%2d f[%d]+%d=%d\n",j,f[j],j-k*v,k*w,f[j-k*v]+k*w);

在这里插入图片描述

控制台第一行,代表2组数据,背包总体积为9
第二行是,第一种物品,体积为2,价值为4,件数为3!
接下来就是f数组更新过程,可以看到左边那列为f[j],右边那列为f[j-kv]+kw,整条f的信息也就是动态转移方程。

重点来了,通过上述规律,我可以将f[9],f[7],f[5],f[3],f[1]归于一类
同理,我将f[8],f[6],f[4],f[2],f[0]归于一类!

那么为什么会得到这样的规律呢? (分析一波,走你~~~~)
首先背包总体积为9,第一件物品体积为2,那么我最多放4件,但是只有三件,所以红框的高度最多为3。

那么为什么分两类呢? 这与物品体积有关! 9,7,5,3,1对体积2取余数,结果都为1,
0,2,4,6,8对体积取余为0!
那么可以得到一般性规律我们可以分出以0~(v-1)开头的k个类
这组数据,就是以0、1开头,1就是v-1即2-1。

下面就要用到单调队列滑动区间的知识,如果对单调队列滑动区间不熟悉,那么很难理解,所以大家不要好高骛远,先把上面的链接看了!如果懂得单调队列滑动区间知识的我们往下看!

在这里插入图片描述

我们再来看这张图,上边说过类的概念,在同一类中,红框依次向下更新,像不像一个滑动区间,我需要找出,窗口内右边那列的的最大值然后赋值给f[j]。

那么如何找出窗口内的最大值呢,或者说如何维护窗口内的最大值呢?

答案就是用单调队列
这道题我们的单调队列一定是从小到大(f[1]~f[9]这个顺序更新)来维护,每次放入队列中较大元素的下标,队首永远是窗口内的最大值。如果从上一个窗格滑动到下一个窗格如果此时队首下标不在这个窗格中,我们就不能用这个队首来更新最大值,需要把队首踢出去也就是head++操作,用新的head来更新,当前窗口最大值。
有了单调队列维护,每次更新f[j]只需要一次操作!而不是三次操作!

(注意:这个较大元素是包括了f[j-kv]+kw是他们一起,而不是单个的f[j-k*v])

举例: f[0] 、f[2]、f[4]、f[6]、f[8]
此时需要更新f[8],但是f[8]是能装下3件的,所以窗口大小为3,但此时单调队列队首停在f[0],那么我就需要将f[0]出队,然后从f[2],f[4],f[6]中选出最大的作为队首,来更新!(我只是举例,实际选最大还要加上k*w)

针对单调队列,不知道大家有没有几个问题?
一、这道题用的单调队列从小到大更新,会产生什么后果呢?如何解决呢?

举例,比如我刚刚更新的f[7],然后我去更新f[9],通过上面的例子可以知道,要想更新f[9],就需要f[7],f[5],f[3],但是f[7],f[5],f[3]都已经更新过了,我们就不能在用了!(因为我是从f[1]~f[9]这么更新过来的)
(如果这个不明白,那么证明01背包问题理解不透彻,不如再看看01背包再过来!)

解决措施:我新添加一个数组g存放f数组的初始值,也就是还没有更新的f数组的值,然后将g数组用单调队列维护,每次更新f中的值我只需要从g中所对应的窗口选出最大的即可!
举例,我想更新f[8],我就从g[6],g[4],g[2]中选出最大的给f[8],就可以了!

这是顺序更新,从f[0]~f[8],红框代表单调队列维护过程,并且用了g数组!
在这里插入图片描述
说了这么多那么单调队列里到底存个啥呢?存窗口中最大的值,还是下标呢?

答案是下标,下标方便我们判断队首是否在滑动窗口中,并且下标好维护!

代码

#include <iostream>using namespace std;const int N = 1010, M = 20010;int n, m;
int v[N], w[N], s[N];
int f[N][M];
int q[M];int main()
{cin >> n >> m;for (int i = 1; i <= n; ++ i) cin >> v[i] >> w[i] >> s[i];for (int i = 1; i <= n; ++ i){for (int r = 0; r < v[i]; ++ r){int hh = 0, tt = -1;for (int j = r; j <= m; j += v[i]){while (hh <= tt && j - q[hh] > s[i] * v[i]) hh ++ ;while (hh <= tt && f[i - 1][q[tt]] + (j - q[tt]) / v[i] * w[i] <= f[i - 1][j]) -- tt;q[ ++ tt] = j;f[i][j] = f[i - 1][q[hh]] + (j - q[hh]) / v[i] * w[i];}}}cout << f[n][m] << endl;return 0;
}

在这里插入图片描述
在这里插入图片描述

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

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

相关文章

作业08.13

一、TCP机械臂测试 通过w(红色臂角度增大)s&#xff08;红色臂角度减小&#xff09;d&#xff08;蓝色臂角度增大&#xff09;a&#xff08;蓝色臂角度减小&#xff09;按键控制机械臂 注意&#xff1a;关闭计算机的杀毒软件&#xff0c;电脑管家&#xff0c;防火墙 1&#x…

CRC校验算法详解、C语言实现

一、前言 1.1 CRC算法介绍 CRC&#xff08;Cyclic Redundancy Check&#xff09;校验算法是一种广泛应用于数据通信和存储系统中的错误检测方法&#xff0c;主要用于检测数据在传输过程中是否发生了改变。CRC算法通过计算一个固定长度的校验码&#xff0c;将该校验码附加到原…

Linux:进程

先了解一下这篇的基础知识 操作系统简述-CSDN博客还有这篇 ok我们来说进程 进程是什么&#xff1f; 在Windows下我们按下EscCtrlShift召唤任务管理器&#xff0c;查看Windows下的进程 我们的进程也是由操作系统管理的&#xff0c;操作系统对进程的管理也是先描述再组织。 …

Docker Hub 镜像代理加速

因为未知原因&#xff0c;docker hub 已经不能正常拉取镜像&#xff0c;可以使用以下代理服务来进行&#xff1a; "https://docker.m.daocloud.io", "https://noohub.ru", "https://huecker.io", "https://dockerhub.timeweb.cloud"…

更深层的理解视觉Transformer, 对视觉Transformer的剖析

写在前面&&笔者的个人理解 目前基于Transformer结构的算法模型已经在计算机视觉&#xff08;CV&#xff09;领域展现出了巨大的影响力。他们在很多基础的计算机视觉任务上都超过了之前的卷积神经网络&#xff08;CNN&#xff09;算法模型&#xff0c;下面是笔者找到的…

无字母绕过webshell

目录 代码 payload构造 php7 php5 构造payload 代码 不可以使用大小写字母、数字和$然后实现eval的注入执行 <?php if(isset($_GET[code])){$code $_GET[code];if(strlen($code)>35){die("Long.");}if(preg_match("/[A-Za-z0-9_$]/",$code))…

JavaEE 的入门

1. 学习JavaEE Java EE(Java Platform Enterprise Edition), Java 平台企业版. 是JavaSE的扩展, ⽤于解决企业级的开 发需求, 所以也可以称之为是⼀组⽤于企业开发的Java技术标准. 所以, 学习JavaEE主要是学习Java在 企业中如何应⽤. 前⾯学习的是Java基础, JavaEE 主要学习Jav…

easyExcel2.1.6自动trim()的问题

环境&#xff1a;easyExcel 2.1.6 问题&#xff1a;easyExcel会自动忽略String中的空格&#xff0c;调用trim()函数&#xff0c;导致excel中的空格失效。 代码如上所示&#xff0c;所以只需要把globalConfiguration的autoTrim()&#xff0c;设置为false即可 那么怎么设置confi…

【区块链+金融服务】河北股权交易所综合金融服务平台 | FISCO BCOS应用案例

区域性股权市场是我国资本市场的重要组成部分&#xff0c;是多层次资本市场体系的基石。河北股权交易所&#xff08;简称&#xff1a;河交所&#xff09; 作为河北省唯一一家区域性股权市场运营机构&#xff0c;打造河北股权交易所综合金融服务平台&#xff0c;将区块链技术与区…

Linux centos stream 9命令及源码

学过linux操作系统的人,对文件、命令比较熟悉。最多的操作是用命令处理文件。 随着学习的深入,会提出疑问:命令长什么样? 出于好奇,会找到命令存放的地方,用cat命令看一下,结果可想而知。 我们知道,命令分内部命令和外部命令,存放在不同的位置。外部命令就是一个可执…

OpenAI API error: “Unrecognized request argument supplied“

题意&#xff1a;OpenAI API 错误&#xff1a;‘提供了无法识别的请求参数’ 问题背景&#xff1a; Im receiving an error when calling the OpenAI API. Its not recognizing file argument, which I submitted to the API. 我在调用 OpenAI API 时遇到错误。API 不识别我提…

HikariCP连接池:Possibly consider using a shorter maxLifetime value.

相关的SQL总结&#xff1a; session级别&#xff1a; show variables like %timeout%; mysql的global级别&#xff1a; show global variables like %timeout%; # 对应 mysql 修改配置&#xff08;单位 秒&#xff09; set global wait_timeout300; set global interacti…

C++结构体指针强制转换以处理电力系统IEC103报文

前言 最近依旧是开发规约解析工具的103篇&#xff0c;已经完成了通用分类服务部分的解析&#xff0c;现在着手开始搞扰动数据传输&#xff0c;也就是故障录波的传输。 在103故障录波&#xff08;扰动数据&#xff09;的报文中&#xff0c;数据是一个数据集一个数据集地存放&a…

51单片机学习记录-数码管操作

这里实现了静态数码管的显示。51单片机一共有可以显示4个数字&#xff0c;可以通过控制P2(4-2)的端口选择8个数字显示器中的一个显示数字&#xff0c;控制P0端口写入显示的数值信息。将操作的逻辑使用了函数Nixie进行了封装。 #include <8051.h>unsigned char NixieTabl…

思科默认路由配置2

#路由协议实现# #任务二默认路由配置2# #1配置计算机的IP地址、子网掩码和网关 #2配置Router-A的名称及其接口IP地址 Router(config)#hostname Router-A Router-A(config)#int g0/0 Router-A(config-if)#ip add 192.168.1.1 255.255.255.0 Router-A(config-if)#no shutdow…

Selenium + Python 自动化测试07(滑块的操作方法)

我们的目标是&#xff1a;按照这一套资料学习下来&#xff0c;大家可以独立完成自动化测试的任务。 本篇文章主要讲述如何操作滑块。 目前很多系统登录或者注册的页面都有滑块相关的验证&#xff0c;selenium 中对滑块的基本操作采用了元素的拖曳的方式。需要用到Actiochains模…

应用兼容性问题-abi动态库错误分析和解决

1&#xff0c;应用名和现象 运行环境&#xff1a; 云手机 现象&#xff1a; 2&#xff0c;分析 --------- beginning of crash 08-14 03:59:59.014 28740 28740 E AndroidRuntime: FATAL EXCEPTION: main 08-14 03:59:59.014 28740 28740 E AndroidRuntime: Process: com.ks…

大型、复杂、逼真的安全服和安全帽检测:数据集和方法

智能升级工地安全&#xff1a;SFCHD数据集与SCALE模块介绍 在人工智能&#xff08;AI&#xff09;技术飞速发展的今天&#xff0c;其在建筑工地安全领域的应用正逐渐展现出巨大潜力。尤其是高风险行业如化工厂的施工现场&#xff0c;对工人的保护措施要求极为严格。个人防护装…

十四、迭代器模式

文章目录 1 基本介绍2 案例2.1 Aggregate 接口2.2 Iterator 接口2.3 MyArray 类2.4 MyArrayIterator 类2.5 Client 类2.6 Client 类的运行结果2.7 总结 3 各角色之间的关系3.1 角色3.1.1 Aggregate ( 集合 )3.1.2 Iterator ( 迭代器 )3.1.3 ConcreteAggregate ( 具体的集合 )3.…

Luminar Neo for Mac/Win:创新AI图像编辑软件的强大功能

Luminar Neo&#xff0c;这款由Skylum公司倾力打造的图像编辑软件&#xff0c;为Mac和Windows用户带来了前所未有的创作体验与编辑便利。作为一款融合了先进AI技术的图像处理工具&#xff0c;Luminar Neo以其独特的功能和高效的操作流程&#xff0c;成为了摄影师、设计师及摄影…