背包问题模板

news2025/4/23 14:36:47

文章目录

    • 01背包
          • 题意
          • 思路
          • 代码
          • 优化
    • 完全背包
          • 题意
          • 思路
          • 代码
          • 优化
    • 多重背包
          • 题意
          • 思路
          • 代码
          • 优化
    • 分组背包
          • 题意
          • 思路
          • 代码

01背包

特点:每件物品最多只能用一次

01背包问题

题意

给出每件物品的体积v,价值w,求解能装入背包的的物品的最大价值,并且每件物品只能选一次

思路

那么这道题就是典型的01背包问题,对于每件物品都存在两种状态,选还是不选。

就像以下图展现的那样,同时我们还要注意,在选择第i件物品时,要判断背包能否放得下。

在这里插入图片描述

代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
int a[10000];
int f[10000][10000];
signed main()
{
	int n,m;
	cin>>n>>m;
	
	 for(int i=1;i<=n;i++)
	 {
	 	int v,w;
	 	cin>>v>>w;
	 	for(int j=0;j<=m;j++)
	 	{
	 		f[i][j]=f[i-1][j];
	 		if(j>=v)
	 		f[i][j]=max(f[i][j],f[i][j-v]+w);
		 }
	  } 
	  cout<<f[n][m]<<endl;
}

优化

现在我们对他进行优化,使用一维数组

1.将二维数组转换为一维数组

我们发现,在用二维数组进行计算时,我们的f[i] [j] 与f[i-1] [j] 时相互独立的,但换成一维数组后,f[j]并不能很好的区分f[i] [j] 与f[i-1] [j],所以我们使用逆序。

2.只有在j>=v时,才会选择第i件物品,那我们逆序结束标志就变成了j>=v。


#include<bits/stdc++.h>
using namespace std;
#define int long long
int a[10000];
int f[10000];
signed main()
{
	int n,m;
	cin>>n>>m;
	
	 for(int i=1;i<=n;i++)
	 {
	 	int v,w;
	 	cin>>v>>w;
	 	for(int j=m;j>=v;j--)
	 	{//这里的f[i][j]=f[i-1][j]也去掉是因为用一维数组表示f[j]=f[j],没多大意义
	 		f[j]=max(f[j],f[j-v]+w);
		 }
	  } 
	  cout<<f[m]<<endl;
}

完全背包

特点:每件物品有无限个

题意

给出每件物品的体积v,价值w,求解能装入背包的的物品的最大价值,并且每件物品能选无限次。

思路

对于每件物品的状态,我们可以不选,也可以选k件

在这里插入图片描述

代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
int a[10000];
int f[10000][10000];
void solve()
{
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		int v,w;
		cin>>v>>w;
		for(int j=0;j<=m;j++)
		  for(int k=0;k*v<=j;k++)
		  f[i][j]=max(f[i][j],f[i-1][j-v*k]+w*k); 
	}
	cout<<f[n][m]<<endl;
}
signed main()
{
	int t=1;
//	cin>>t; 
	while(t--)
	solve();	
}

优化

代码优化

1.这样替换过后,就不必要开第三层循环。

在这里插入图片描述

2.我们再回顾01背包 f[i] [j] =max( f[i] [j], f[i-1] [j-v]+w)

那同样的我们可以将他准换一维数组,但有所不同的就是,我们不用再担心会将i-1个物品覆盖。

#include<bits/stdc++.h>
using namespace std;
#define int long long
int a[10000];
int f[10000];
void solve()
{
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		int v,w;
		cin>>v>>w;
		for(int j=v;j<=m;j++)
		  f[j]=max(f[j],f[j-v]+w); 
	}
	cout<<f[m]<<endl;
}
signed main()
{
	int t=1;
//	cin>>t; 
	while(t--)
	solve();	
}

多重背包

特点:每件物品可以用有限个

题意

给出每件物品的体积v,价值w,求解能装入背包的的物品的最大价值,并且每件物品的个数是有限的

思路

那我们就发现了,我们的多重背包与完全背包的朴素计算方法是类似的,唯一要注意的就是,我们第三层循环的k要小于等于物品个数。

代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
int a[10000];
int f[10000][10000];
void solve()
{
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		int v,w,s;
		cin>>v>>w>>s;
		for(int j=0;j<=m;j++)
		  for(int k=0;k*v<=j&&k<=s;k++)
		  f[i][j]=max(f[i][j],f[i-1][j-v*k]+w*k); 
	}
	cout<<f[n][m]<<endl;
}
signed main()
{
	int t=1;
//	cin>>t; 
	while(t--)
	solve();	
}
优化

那么这里就存在疑问了,为什么不能像完全背包一样优化?

在这里插入图片描述

将其展开我们发现,并不能通过知道五个数的最大值,推出来前4个数的最大值。所以这种优化方式是错的。

这里我们有一个小技巧,使用二进制去优化。

用二进制去打包这些物品,比如说我有10个物品,我按照二进制,将其打包成

1,2,4,以及最后剩下的3。这样我们去询问时,就是第一堆(1个)物品取还是不取,第二堆(2个)物品取还是不取…。也就是将他转换成了01背包的问题。

#include<bits/stdc++.h>
using namespace std;
#define int long long
int v[100000],w[100000];
int f[100000];
void solve()
{
	int n,m;
	cin>>n>>m;
	int cnt=0;
	for(int i=1;i<=n;i++)//在此处理分组问题,
	{
		int a,b,s;
		cin>>a>>b>>s;
		int k=1;//标记二进制的大小
		while(k<=s)
		{
			cnt++;//用来记录第几组
			v[cnt]=a*k;//每组的体重
			w[cnt]=b*k;//每组的价值
			s-=k;k*=2;//更新剩余数量,以及每组分配的大小
		 } 
		 if(s>0)//判断是否还有剩余的没有分配
		 {
		 	cnt++;
		 	v[cnt]=a*s;
		 	w[cnt]=b*s;
		  } 
	 } 
	 n=cnt;//更新
    //用01背包解决
	 for(int i=1;i<=n;i++)
	 {
	 	for(int j=m;j>=v[i];j--)
	 	{
	 		f[j]=max(f[j],f[j-v[i]]+w[i]);
		 }
	 }
	 cout<<f[m]<<endl;
	 
}
signed main()
{
	int t=1;
//	cin>>t; 
	while(t--)
	solve();	
}

分组背包

特点:每组最多可以选一个物品

题意

给出每件物品的体积与价值。每组有若干个物品,最多只能选一个,求解能装入背包的的物品的最大价值。

思路

在这里插入图片描述

代码

这里优化和上边类似,就不再描述了。

#include<bits/stdc++.h>
using namespace std;
#define int long long
int f[10000];
int v[11000][10000];
int w[10000][10000];
int s[100000];
signed main()
{
	int n,m;
	cin>>n>>m;
	
	 for(int i=1;i<=n;i++)
	 {
	 	cin>>s[i];
	 	for(int j=0;j<s[i];j++)
	 	{
	 		cin>>v[i][j]>>w[i][j];
		 }
	  } 
    for(int i=1;i<=n;i++)
    {
        for(int j=m;j>=0;j--)
            for(int k=0;k<s[i];k++)
            if(v[i][k]<=j)
                f[j]=max(f[j],f[j-v[i][k]]+w[i][k]);
    }
	  cout<<f[m]<<endl;
}

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

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

相关文章

Sentinel源码—8.限流算法和设计模式总结二

大纲 1.关于限流的概述 2.高并发下的四大限流算法原理及实现 3.Sentinel使用的设计模式总结 3.Sentinel使用的设计模式总结 (1)责任链模式 (2)监听器模式 (3)适配器模式 (4)模版方法模式 (5)策略模式 (6)观察者模式 (1)责任链模式 一.责任链接口ProcessorSlot 二.责…

VulnHub-DarkHole_1靶机渗透教程

VulnHub-DarkHole_1靶机渗透教程 1.靶机部署 [Onepanda] Mik1ysomething 靶机下载&#xff1a;https://download.vulnhub.com/darkhole/DarkHole.zip 直接使用VMware打开就行 导入成功&#xff0c;打开虚拟机&#xff0c;到此虚拟机部署完成&#xff01; 注意&#xff1a…

边缘计算全透视:架构、应用与未来图景

边缘计算全透视&#xff1a;架构、应用与未来图景 一、产生背景二、本质三、特点&#xff08;一&#xff09;位置靠近数据源&#xff08;二&#xff09;分布式架构&#xff08;三&#xff09;实时性要求高 四、关键技术&#xff08;一&#xff09;硬件技术&#xff08;二&#…

MQ底层原理

RabbitMQ 概述 RabbitMQ 是⼀个开源的⾼性能、可扩展、消息中间件&#xff08;Message Broker&#xff09;&#xff0c;实现了 Advanced Message Queuing Protocol&#xff08;AMQP&#xff09;协议&#xff0c;可以帮助不同应⽤程序之间进⾏通信和数据交换。RabbitMQ 是由 E…

本地部署DeepSeek-R1模型接入PyCharm

以下是DeepSeek-R1本地部署及接入PyCharm的详细步骤指南,整合了视频内容及官方文档核心要点: 一、本地部署DeepSeek-R1模型 1. 安装Ollama框架 ​下载安装包 访问Ollama官网(https://ollama.com/download)Windows用户选择.exe文件,macOS用户选择.dmg包。 ​安装验证 双击…

Java基于SpringBoot的企业车辆管理系统,附源码+文档说明

博主介绍&#xff1a;✌Java老徐、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&…

进阶篇 第 2 篇:自相关性深度解析 - ACF 与 PACF 图完全指南

进阶篇 第 2 篇&#xff1a;自相关性深度解析 - ACF 与 PACF 图完全指南 (图片来源: Negative Space on Pexels) 欢迎来到进阶系列的第二篇&#xff01;在上一篇&#xff0c;我们探讨了更高级的时间序列分解技术和强大的指数平滑 (ETS) 预测模型。ETS 模型通过巧妙的加权平均捕…

鸿蒙移动应用开发--渲染控制实验

任务&#xff1a;使用“对象数组”、“ForEach渲染”、“Badge角标组件”、“Grid布局”等相关知识&#xff0c;实现生效抽奖卡案例。如图1所示&#xff1a; 图1 生肖抽奖卡实例图 图1(a)中有6张生肖卡可以抽奖&#xff0c;每抽中一张&#xff0c;会通过弹层显示出来&#xf…

安宝特分享|AR智能装备赋能企业效率跃升

AR装备开启智能培训新时代 在智能制造与数字化转型浪潮下&#xff0c;传统培训体系正面临深度重构。安宝特基于工业级AR智能终端打造的培训系统&#xff0c;可助力企业构建智慧培训新生态。 AR技术在不同领域的助力 01远程指导方面 相较于传统视频教学的单向输出模式&#x…

SpringCloud组件—Eureka

一.背景 1.问题提出 我们在一个父项目下写了两个子项目&#xff0c;需要两个子项目之间相互调用。我们可以发送HTTP请求来获取我们想要的资源&#xff0c;具体实现的方法有很多&#xff0c;可以用HttpURLConnection、HttpClient、Okhttp、 RestTemplate等。 举个例子&#x…

模型 螃蟹效应

系列文章分享模型&#xff0c;了解更多&#x1f449; 模型_思维模型目录。个体互钳&#xff0c;团队难行。 1 螃蟹效应的应用 1.1 教育行业—优秀教师遭集体举报 行业背景&#xff1a;某市重点中学推行绩效改革&#xff0c;将班级升学率与教师奖金直接挂钩&#xff0c;打破原…

符号速率估计——小波变换法

[TOC]符号速率估计——小波变换法 一、原理 1.Haar小波变换 小波变换在信号处理领域被成为数学显微镜&#xff0c;不同于傅里叶变换&#xff0c;小波变换可以观测信号随时间变换的频谱特征&#xff0c;因此&#xff0c;常用于时频分析。   当小波变换前后位置处于同一个码元…

每日算法-250422

每日算法 - 250422 1561. 你可以获得的最大硬币数目 题目 思路 贪心 解题过程 根据题意&#xff0c;我们想要获得最大的硬币数目。每次选择时&#xff0c;有三堆硬币&#xff1a;最大的一堆会被 Alice 拿走&#xff0c;最小的一堆会被 Bob 拿走&#xff0c;剩下的一堆&#xf…

【MATLAB第116期】基于MATLAB的NBRO-XGBoost的SHAP可解释回归模型(敏感性分析方法)

【MATLAB第116期】基于MATLAB的NBRO-XGBoost的SHAP可解释回归模型&#xff08;敏感性分析方法&#xff09; 引言 该文章实现了一个可解释的回归模型&#xff0c;使用NBRO-XGBoost&#xff08;方法可以替换&#xff0c;但是需要有一定的编程基础&#xff09;来预测特征输出。该…

微信公众号消息模板推送没有“详情“按钮?无法点击跳转

踩坑&#xff01;&#xff01;&#xff01;&#xff01;踩坑&#xff01;&#xff01;&#xff01;&#xff01;踩坑&#xff01;&#xff01;&#xff01;&#xff01; 如下 简单说下我的情况&#xff0c;按官方文档传参url了 、但就是看不到查看详情按钮 。如下 真凶&#x…

电动单座V型调节阀的“隐形守护者”——阀杆节流套如何解决高流速冲刷难题

电动单座V型调节阀的“隐形守护者”——阀杆节流套如何解决高流速冲刷难题&#xff1f; 在工业自动化控制中&#xff0c;电动单座V型调节阀因其精准的流量调节能力&#xff0c;成为石油、化工等领域的核心设备。然而&#xff0c;长期高流速工况下&#xff0c;阀芯与阀座的冲刷腐…

自动驾驶与机器人算法学习

自动驾驶与机器人算法学习 直播与学习途径 欢迎你的点赞关注~

【网络编程】TCP数据流套接字编程

目录 一. TCP API 二. TCP回显服务器-客户端 1. 服务器 2. 客户端 3. 服务端-客户端工作流程 4. 服务器优化 TCP数据流套接字编程是一种基于有连接协议的网络通信方式 一. TCP API 在TCP编程中&#xff0c;主要使用两个核心类ServerSocket 和 Socket ServerSocket Ser…

从零开始配置 Zabbix 数据库监控:MySQL 实战指南

Zabbix作为一款开源的分布式监控工具&#xff0c;在监控MySQL数据库方面具有显著优势&#xff0c;能够为数据库的稳定运行、性能优化和故障排查提供全面支持。以下是使用Zabbix监控MySQL数据库的配置。 一、安装 Zabbix Agent 和 MySQL 1. 安装 Zabbix Agent services:zabbix…

Java学习手册:RESTful API 设计原则

一、RESTful API 概述 REST&#xff08;Representational State Transfer&#xff09;即表述性状态转移&#xff0c;是一种软件架构风格&#xff0c;用于设计网络应用程序。RESTful API 是符合 REST 原则的 Web API&#xff0c;通过使用 HTTP 协议和标准方法&#xff08;GET、…