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

背包九讲——混合背包问题

 

 背包问题第四讲——混合背包问题

背包问题是一类经典的组合优化问题,通常涉及在限定容量的背包中选择物品,以最大化某种价值或利益。问题的一般描述是:有一个背包,其容量为C;有一组物品,每个物品有重量w和价值v。目标是选择一些物品放入背包,使得它们的总重量不超过背包容量,同时总价值最大。
混合背包问题则是既有01背包、多重背包和完全背包,混合背包的物品特征是这三个或者两个背包特征的综合。

 混合背包问题 

混合背包问题是一类组合优化问题,它结合了01背包问题、完全背包问题和多重背包问题的特点。在混合背包问题中,有多种物品和一个固定容量的背包,每种物品有自己的重量和价值,并且每种物品可能有使用次数的限制。

三类背包:

具体来说,混合背包问题中的物品可以分为三类:

  1. 第一类物品只能用1次(01背包);
  2. 第二类物品可以用无限次(完全背包);
  3. 第三类物品最多只能用si次(多重背包)。

目标是在不超过背包容量的前提下,选择物品装入背包,使得物品总价值最大。


问题定义:

混合背包问题是背包问题的另一种变体,结合了0/1背包、多重背包和完全背包的特点。在混合背包问题中,每种物品可以选择放入背包的次数是有限的,而且也可以选择放入的数量是无限的。
问题的描述如下:
给定一个背包容量为m,有n种物品,每种物品有重量v[i]、价值w[i]、以及数量s[i]。其中,s[i]表示第i种物品的数量限制。目标是选择物品放入背包,使得它们的总重量不超过背包容量,并且总价值最大。

解决方法:

解决混合背包问题的方法需要考虑每种物品的数量限制。可以将问题拆分为若干个子问题,对于每种物品分别处理。可以采用动态规划的方法,类似于多重背包问题,但需要考虑不同物品的数量限制。一种常见的方法是将每种物品拆分成多个子物品,其中每个子物品对应放入背包的数量。然后,可以使用类似于多重背包问题的解法来处理这个扩展后的问题。
总体而言,解决混合背包问题需要综合考虑每种物品的多重性和数量限制,选择适当的方法进行求解。

这个多重背包无非就是01背包、多重背包、完全背包混合起来罢了,根据是什么背包,分类讨论就好了,当s==-1的时候就是01背包,当s==0的时候就是完全背包,当s>0的时候就是多重背包,三个if判断便可以分类解决,对前面01背包、多重背包、完全背包不熟悉的可以看一下我之前写的博客,这里不再详细讲解。

我们根据分类讨论解决01背包、多重背包、完全背包问题,通常使用动态规划的方法。动态规划的关键在于定义状态和状态转移方程。对于混合背包问题,可以定义一个二维数组dp[i][j],其中dp[i][j]表示考虑前i种物品,背包容量为j时的最大价值。

状态转移方程需要根据物品的使用限制来确定:

  • 对于01背包问题,状态转移方程为:dp[i][j] = max(dp[i-1][j], dp[i-1][j-v[i]] + w[i]),其中v[i]和w[i]分别是第i种物品的体积和价值。
  • 对于完全背包问题,状态转移方程为:dp[i][j] = max(dp[i-1][j], dp[i][j-v[i]] + w[i])
  • 对于多重背包问题,需要遍历物品的使用次数,更新状态转移方程。

代码实现:

这里01背包动态规划、多重背包的二进制解法、完全背包的动态规划方法为例,进行C++实现。如果考虑优化可以看一下多重背包的单调队列解法。

题目以这个为例,可以去提交验证:7. 混合背包问题 - AcWing题库

#include<iostream>
using namespace std;
int v[1005],w[1005],s[1005];//s[i]表示物品特性,是01还是多重还是完全
int n,m;
int dp[10005],vis[10005];//vis[i]==1表示第i个物品是完全背包,==0表示01背包
int v1[10005],w1[10005];//最终转换成的01背包和完全背包
int main(){
	int index=0;
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>v[i]>>w[i]>>s[i];
	}
	for(int i=1;i<=n;i++){
		if(s[i]==0){//完全背包问题
		    vis[++index]=1;
			v1[index]=v[i];
			w1[index]=w[i];
			continue;
		}
		if(s[i]==-1){//01背包问题
			v1[++index]=v[i];
			w1[index]=w[i];
			continue;
		}
		//多重背包问题
		for(int j=1;j<=s[i];j<<=1){
			s[i]-=j;
			v1[++index]=j*v[i];
			w1[index]=j*w[i];
		}
		if(s[i]){
			v1[++index]=s[i]*v[i];
			w1[index]=s[i]*w[i];
			s[i]=0;
		}
	}
	for(int i=1;i<=index;i++){
		if(vis[i]==1){//完全背包
			for(int j=v1[i];j<=m;j++){
				dp[j]=max(dp[j],dp[j-v1[i]]+w1[i]);
			}
		}else{//01背包
			for(int j=m;j>=v1[i];j--){
				dp[j]=max(dp[j],dp[j-v1[i]]+w1[i]);
			}
		}
	}
	cout<<dp[m]<<endl;
	return 0;
}

上一篇文章完全背包问问题:背包九讲——完全背包问题-CSDN博客

背包问题是经典之经典,每一位算法入门学者必学的内容,里面的优化涉及到的也非常具有思维性,值得大家好好学习。由于笔者水平有限,一些方面可能也存在着问题,望大家理解支持,有错误就指出改正,大家一起进步,执笔至此,感触彼多,全文将至,落笔为终,感谢各位的支持,下篇更新二维费用背包问题


http://www.kler.cn/news/367562.html

相关文章:

  • 音视频同步版本【基于音频】
  • python源码编译—Cython隐藏源码(windows)
  • 论文笔记(五十一)Challenges for Monocular 6-D Object Pose Estimation in Robotics
  • 面向对象与设计模式第二节:设计模式实战
  • 基于物联网的智慧考场系统设计(论文+源码)
  • Java-图书管理系统
  • 虾类图像分割系统:改进亮点优化
  • 前端项目接入sqlite轻量级数据库sql.js指南
  • ffmpeg视频滤镜: 色温- colortemperature
  • Windows 11 绕过 TPM 方法总结,24H2 通用免 TPM 镜像下载 (Updated Oct 2024)
  • java项目之在线考试系统设计与实现(springboot)
  • 通过AWS Bedrock探索 Claude 的虚拟桌面魔力:让 AI 代替你动手完成任务!
  • 时间数据可视化基础实验(南丁格尔玫瑰图)——Python热狗大胃王比赛数据集
  • 蓝桥杯普及题
  • Android中导入讯飞大模型ai智能系统
  • nodejs写入日志文件
  • Linux: Shell编程中的应用之基于sh进行数据统计
  • 【C++ 真题】B2106 矩阵转置
  • 基于java SpringBoot和Vue校园求职招聘系统设计
  • 【牛客算法】某司面试算法题:设计LRU缓存结构
  • static 关键字的用法
  • 【Java】LinkedList实现类的使用
  • 苹果预告下周发布Mac新品:全系标配M4系列芯片
  • 前端处理API接口故障:多接口自动切换的实现方案
  • bluez hid host介绍,连接键盘/鼠标/手柄不是梦,安排
  • 日常实习与暑期实习详解