【背包题解】DP代表了走到阶段i 的所有路线的最优解

目录

1889:【提高】多重背包(2)

二维费用背包

2075 - 最大卡路里

1928 - 采购礼品


背包容量:(c)

6

重量

weight

2

2

4

6

2

1

2

3

4

5

价值

value

3

6

5

5

8

1

2

3

4

5

wv
dp数组:记录有i件物品,背包容量为j的情况下,最大价值
nameweightvalue123456
a23033333
b2606/66+dp[i-1][j-w[i]]=999
c45
d65
e28

第i件物品  

w[i]>c:放不下,最大价值=i-1件物品讨论时的最大价值

选:剩余容量=c-w[i],最大价值=v[i]+(i-1件物品,容量在 c-w[i]的情况下最大价值)

w[i]<=c:放得下

不选:最大价值=i-1件物品讨论时的最大价值

dp[i][j]

w[i]>c:放不下,最大价值 =dp[i-1][j]

选,最大价值 =v[i]+ dp[i-1][c--w[i]]

w[i]<=c:放得下,最大价值

不选,最大价值 =dp[i-1][j]

动态转移方程:

dp[i][j]=max(dp[i-1][j],v[i]+dp[i-1][j-w[i]])

1889:【提高】多重背包(2)

题目描述

有 N 种物品和一个容量是 V的背包。

第 ii种物品最多有 si​ 件,每件体积是 vi​,价值是 wi​ 。

求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。

输出最大价值。

关于 DP要理解的关键点:

1 DP的本质

求有限的集合中的最值(个数)

本质上,DP代表了走到阶段i 的所有路线的最优解

2 DP需要思考的点:

(1)DP 的状态是什么?状态要求什么:最大、最小、数量?

(2)DP   的状态计算?

状态转义方程;

求解方法: a 、递推  b、考虑阶段i  (最后一个阶段的值)的值是如何得来的

(3)DP   的边界是什么?

关键术语:阶段、状态、决策(状态转移方程)、边界;

以数塔问题(1216:【基础】数塔问题)为例,理解DP 的本质,再理解01背包的本质 (1282:【提高】简单背包问题);

经典的 DP模板题要熟练掌握,熟记状态转义方程!

本题解题的关键点:二进制优化(类似压缩的思想)

( 1 ) 有n 个不同的物品,要讨论2"种选择的可能(每个物品选或者不选);

(2)一个物品有n 件,虽然要讨论2"种选择的可能,但由于n 个物品是一样的,那么 就减少了讨论数量,比如:有4个物品,如果是不同物品的选2个,选12、23是不同的 选择,但如果是相同的物品,选哪两个就都是一样的了。

因此,n 个物品,要讨论的可能就分别是:选0个、选1个、选2个、选3个…选n 个。 (3)要将0~n 个不同的选择表达出来,比较简单的方法是将n 二进制化。

比如:整数7,只需要用124三个数任意组合,就能组合出0~7这8种可能。

再比如:整数10,只需要用1243(注意最后一个数),就能组合出0~10这11种可 能,这样 n 这个值就被二进制化了。

因此如果要讨论10个一样的物品,就转化为讨论4个不同的物品了;而n 个一样的物 品,就转化为log₂n 个不同的物品进行讨论。

dp[j]=max{dp[j],dp[j-w[i]]+v[i]}

#include <bits/stdc++.h>
using namespace std;

const int N=20010;
int v[N],w[N],dp[2010];
int n,m;//n种物品,背包容量为m
int vi,wi,si;
int k=0;
int main() {
	cin>>n>>m;
	for(int i=1; i<= n; i++) {
		cin>>vi>>wi>>si;
		/*对si二进制化,比如:
		有10件一样的物品我们转换为有4件不同的物品:1 2 4 3
		这4种物品的体积分别是:1*vi 2*vi 4*vi 3*vi*/
		int t=1;//权重,表示2的次方
		while(t<= si) {
			k++;
			v[k]= t* vi;
			w[k]=t* wi;
			si =si-t;
			t=t*2;
		}
//如果二进制化有剩余,存入
		if(si >0) {
			k++;
			v[k]= si * vi;
			w[k]= si * wi;
		}
	}

//01 背包
	for(int i=1; i<= k; i++) {
		for(int j= m; j >= v[i]; j--) {
			dp[j]= max(dp[j],dp[j-v[i]]+w[i]);
		}
	}
	cout<<dp[m];
	return 0;
}

二维费用背包

二维费用的背包问题是指:对于每件物品,具有两种不同的费用;选择这件物品必须同 时付出这两种代价;对于每种代价都有一个可付出的最大值(背包容量)。问怎样选择物品 可以得到最大的价值。设这两种代价分别为代价1和代价2,第i 件物品所需的两种代价分  v[i]   w[i]

两种代价可付出的最大值(两种背包容量)分别为maxv  maxw, 物品的价值为c[i]

解决方法: 费用加了一维,只需状态也加一维即

 f[i][j][k]       表示前i 件物品付出两种代价分别,背包体积j,  背包的承重为k 时可

获得的最大价值。

状态转移方程就是:

f[i][j][k]=max(f[i-1][j][k],f[i-1][j-v[i]][k-w[i]]+c[i])

空间优化后,可以用二维数组求解。

f[j][k]=max(f[j][k],f[j-v[i]][k-w[i]]+c[i])

2075 - 最大卡路里

题目描述

神州飞船准备运送一批食品到太空站,该飞船能够运送食品的重量、体积都有严格的限制。

现已知 nn 件完全不同的食品,每种食品的重量、体积及该食品能够提供的卡路里的值,请你编程计算出,该飞船最多能够运送多少卡路里的食物?

#include <bits/stdc++.h>
using namespace std;

const int N=410;
int dp[N][N];//代表求解体积为j,重量为k时能够得到的最大价值
int n,v,w,c;
int maxv,maxw;//背包的上限
int main() {
	cin>>maxv>>maxw;
	cin>>n;
	for(int i=1; i<= n; i++) {
		cin>>v>>w>>c;
		//01 背包
		//从最大体积~当前物品体积降序循环,同理重量也要降序循环
		for(int j= maxv; j >= v; j--) {
			for(int k=maxw; k >= w; k--) {
				dp[j][k]= max(dp[j][k],dp[j-v][k-w]+c);
			}
		}
	}
	cout<<dp[maxv][maxw];//最大价值
	return 0;
}

1928 - 采购礼品

题目描述

王老师来到商店为同学们采购礼品。

这家店有 n 种礼品(编号是 1∼n ),每种礼品只有 1 件。老板为了促销,对礼品进行搭配销售,有关联性的礼品必须都要采购(奇怪的规定),比如 1 号礼品和 3号礼品搭配了,3 号和 8 号礼品搭配了,那么王老师想要买 1 号礼品的话,就需要把 3 号和 8 号礼品都买了。

现给定每种礼品的价钱和价值,请问在有限的钱 w 的情况下,能够买到礼品的最大价值是多少?

输入

第一行输入三个整数,n,m,w,表示有n 种礼品,m 个搭配和你现有的钱的数目。

第二行至 n+1 行,每行有两个整数,c、d,表示第 ii 种礼品的价钱和价值。(1≤c,d≤10^5)

第 n+2 至 n+1+m 行 ,每行有两个整数,u、v,表示 u 号礼品和 vv 号礼品是有关联的,已经形成搭配销售的关系。

数据范围:

1≤n,w≤10^4,0≤m≤5 *10^3。

输出

一行,表示可以获得的最大价值。

样例

输入

5 3 10
3 10
3 10
3 10
5 100
10 1
1 3
3 2
4 2

输出

1

典型的01背包,但要求同一组的物品都要购买。我们可以采用并査集将同一组有关系的礼品的价值、价格汇总到该集合的根节点上,这样就保证了一个集合中的礼品都购买的情况。

它解决的是在有限的预算 w 下,如何选择一组关联的礼品(根据提供的搭配信息),使得这些礼品的价值总和最大。

  1. 定义了几个数组:f 用于并查集,存储物品之间的关系;qv 分别存储物品的价钱和价值;dp 用于动态规划,记录在给定背包容量下的最大价值。

  2. 首先通过并查集对具有关联关系的物品进行合并,确保在考虑搭配时,每个组合中的所有物品都被视为一个整体。

  3. 然后,遍历所有物品,如果某物品不是其自身的根节点,说明这个物品已经被包含在某个组合中,需要更新根节点的价钱和价值。

  4. 接着进行动态规划计算。从背包容量 w 到每种物品的价钱(降序),尝试是否可以添加当前物品,如果可以,更新背包的最大价值。

  5. 最后,输出在给定预算 w 下可以获得的最大价值。

  6. 王老师需要在有限的预算 w 下,选择价值最高的礼品组合,但受到了一些特定的搭配规则影响,即如果一种礼品被选中,与其搭配的相关礼品也必须被同时购买。

  7. 具体步骤如下:

  8. 理解问题: 首先,我们需要知道每种礼品的价值(d)和价格(c),以及哪些礼品之间存在强制搭配关系(由uv表示)。这是一个二维背包问题,因为搭配关系限制了我们不能单独选择某件礼品。

  9. 模型构建: 可以考虑使用动态规划的方法,比如创建一个二维数组 dp[i][j],其中 i 代表剩余的预算,j 代表剩余的可选礼品数量。dp[i][j] 表示在剩余预算 i 和可以选择的礼品数量 j 下,能获得的最大价值。

  10. 状态转移: 对于每个礼品 k,有两种情况:选择它(增加价值 d[k] 但减少可用预算 c[k]),或不选择它。根据这两种情况,更新 dp 数组。

  11. 处理搭配关系: 在更新 dp 时,要考虑已有的搭配关系。如果礼品 kl 搭配,意味着在包含 k 的情况下,l 也会被强制选择。因此,我们需要更新 dp 时包括这种情况。

  12. 寻找最大价值: 最终的答案就是 dp[w][n],即在预算 w 和所有礼品都可选的情况下,能获得的最大价值。

  13. 输出结果: 返回计算得到的最大价值作为答案。

#include <bits/stdc++.h>
using namespace std;

int f[10100];//存储物品之间的关系
int q[10100],v[10100];//价钱、价值
int dp[10100];//以拥有的钱来定义背包容量
//查:查询元素的根
int find(int x) {
	return f[x]==x?x:f[x]=find(f[x]);
}
//并:合并元素xy
void merge(int x,int y) {
	int fx = find(x);
	int fy = find(y);
	if(fx != fy) {
		f[fx]=fy;
	}
}
int main() {
	int n,m,w;
	cin>>n>>m>>w;//n个物品的价钱和价值
	for(int i = 1; i<= n; i++) {
		cin>>q[i]>>v[i];
		//并查集初始化
		f[i]= i;
	}
	//m个物品的关系
	int x,y;
	for(int i = 1; i<= m; i++) {
		cin>>x>>y;
		merge(x,y);
	}
	//将有关系的物品合并到这组物品的根上司
	for(int i = 1; i<= n; i++) {
		//该物品不是根,则将价钱和价值都合并到根上
		if(f[i] != i) {
			q[find(i)]+=q[i];
			v[find(i)]+=v[i];
			//将该组物品的价钱和价值清零
			q[i]=0;
			v[i]=0;
		}
	}
	//01背包计算结果
	for(int i = 1; i <= n; i++) {
		//从背包容量(有多少钱)~该物品的价钱降序
		for(int j= w; j >= q[i]; j--) {
			dp[j] = max(dp[j],dp[j-q[i]]+v[i]);
		}
	}
	cout<<dp[w];

	return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

作业管理系统

摘 要 随着网络的发展&#xff0c;信息化时代的到来&#xff0c;在教学工作的过程中作用越来越明显&#xff0c;作业的及时发布&#xff0c;学生的及时提交&#xff0c;以及通过网上的批改和评分&#xff0c;都大大促进教学质量的发展&#xff0c;充分的利用网络来加强管理&am…

vue2动态横条图(横条图样式定时切换)

每次切换成新图后会清除定时器和图&#xff08;重新加载&#xff0c;否则要么会重复加载定时器。清除定时器之后要先调用一次index为0的数据&#xff09; 数据样例 acrossBarDatas:{data: ["80", "80"],sunffix: [单位, "单位"],title: "标…

可信启动Trusted Board Boot

TBB Trusted Board Boot&#xff08;TBB&#xff09;对所有固件镜像&#xff08;包括普通世界的bootloader&#xff09;进行身份验证&#xff0c;以防止恶意固件在平台上运行。TBB使用公钥加密标准 &#xff08;PKCS&#xff09;来建立信任链&#xff08;Chain of Trust&#…

Log4j2异步打印可变对象的问题

现象 应用代码如下&#xff1a; Test test new Test();test.setA(1);test.setB("1");log.info("before modification: {} \t ",test);test.setA(2);test.setB("2");log.info("after modification: {} \t ",test);问题应用的日志控制…

怎么添加网页到桌面快捷方式?

推荐用过最棒的学习网站&#xff01;https://offernow.cn 添加网页到桌面快捷方式&#xff1f; 很简单&#xff0c;仅需要两步&#xff0c;接下来以chrome浏览器为例。 第一步 在想要保存的网页右上角点击设置。 第二步 保存并分享-创建快捷方式&#xff0c;保存到桌面即可…

使用VisualBox+Vagrant搭建Centos虚拟机环境

1.下载并安装VisualBox&#xff1b; 2.下载并安装Vagrant; 3.打开cmd窗口&#xff0c;执行命令vagrant init centos/7&#xff0c;初始化centos环境&#xff0c;该步骤受网络带宽影响&#xff0c;可能挂级30分钟到1个小时&#xff1b; 4.启动虚拟机&#xff1a;vagrant up&…

C# yolov8 OpenVINO 同步、异步接口视频推理

C# yolov8 OpenVINO 同步、异步接口视频推理 目录 效果 项目 代码 下载 效果 同步推理效果 异步推理效果 项目 代码 using OpenCvSharp; using System; using System.Collections.Generic; using System.Diagnostics; using System.Threading; using System.Windows.Form…

慢阻肺患者为何容易营养不良?朗格力教你轻松改善

#肺科营养#朗格力#班古营养#复合营养素#肺部营养#肺部健康# 慢阻肺是我国常见的、高患病率的慢性呼吸系统疾病,会对肺结构和功能产生影响,从而引起各种不良反应,其中营养不良是常见并发症之一。慢阻肺为什么会发生营养不良?营养不良又是怎么伤害慢阻肺的呢?为什么像班古精准…

鸿蒙 登录界面示例

1.b站登录界面 我的b站教学视频&#xff1a;https://www.bilibili.com/video/BV1LQgQexEGm/?spm_id_from333.999.0.0&vd_sourced0ea58f1127eed138a4ba5421c577eb1 最终实现效果&#xff1a; 需要准备2张图片&#xff0c;分别是向下和向右边的图标 代码&#xff1a; En…

(2024,Vision-RWKV,线性复杂度双向注意力,四向标记移位)通过类似 RWKV 的架构实现高效且可扩展的视觉感知

Vision-RWKV: Efficient and Scalable Visual Perception with RWKV-Like Architectures 公和众与号&#xff1a;EDPJ&#xff08;进 Q 交流群&#xff1a;922230617 或加 VX&#xff1a;CV_EDPJ 进 V 交流群&#xff09; 目录 0. 摘要 2. 特征聚合机制 3. Vision-RWKV 3.…

一问搞懂Linux信号【上】

Linux信号在Linux系统中的地位仅此于进程间通信&#xff0c;其重要程度不言而喻。本文我们将从信号产生&#xff0c;信号保存&#xff0c;信号处理三个方面来讲解信号。 &#x1f6a9;结合现实认识信号 在讲解信号产生之前&#xff0c;我们先做些预备的工作。 现实生活中信号…

2024.6最最新版MySQL数据库安装(保姆级教程,不懂你捶我)

1.MySQL数据库下载 1.打开MySQL官网 如下页面 2.下翻网页到最底部,找到Download,点击第一个MySQL Community Server 3.选择自己需要的版本以及系统的MySQL: 4.跳转页面会有一个登录/注册页面,这里我们不鸟他,直接开始下载 2.MySQL数据库安装 1.双击我们刚刚下载的安装包 2.勾…

音乐管理系统

摘 要 现如今&#xff0c;在信息快速发展的时代&#xff0c;互联网已经成了人们在日常生活中进行信息交流的重要平台。看起来&#xff0c;听歌只是一种消遣和消遣&#xff0c;其实&#xff0c;只要你选对了曲子&#xff0c;就会产生许多不同的作用。音乐能舒缓身心&#xff0c…

上海交大阿里巴巴推出虚拟试衣新里程碑式工作——AnyFit:任意场景、任意组合!

文章链接&#xff1a;https://arxiv.org/pdf/2405.18172 工程链接&#xff1a;https://colorful-liyu.github.io/anyfit-page/ 今天和大家一起学习的是一种名为AnyFit的新型虚拟试穿系统&#xff0c;旨在解决现有技术在处理不同场景和服饰组合时出现的衣物风格不匹配和质量下…

量化系统--开源强大的qmt交易系统,提供源代码

经过的3天终于写完了qmt_trader的文档了开源直接使用我开源了全部源代码 文档地址 https://gitee.com/li-xingguo11111/qmt_trader 源代码from qmt_trader.qmt_trader import qmt_trader from qmt_trader.xtquant.xttype import StockAccountfrom qmt_trader.xtquant import …

opencascade AIS_InteractiveContext源码学习2

AIS_InteractiveContext 前言 交互上下文&#xff08;Interactive Context&#xff09;允许您在一个或多个视图器中管理交互对象的图形行为和选择。类方法使这一操作非常透明。需要记住的是&#xff0c;对于已经被交互上下文识别的交互对象&#xff0c;必须使用上下文方法进行…

C语言练习03-字符串

一、遍历字符 #include<stdio.h>int main() {char str[100];//录入字符串printf("请输入一串字符&#xff1a;\n");scanf("%s",str);//遍历字符串char* p str;while(1){char c *p;if(c \0){//如果遍历到结束标记&#xff0c;则循环结束break;}//…

雷池社区版自动SSL

正常安装雷池&#xff0c;并配置站点&#xff0c;暂时不配置ssl 不使用雷池自带的证书申请。 安装&#xff08;acme.sh&#xff09;&#xff0c;使用域名验证方式生成证书 先安装git yum install git 或者 apt-get install git 安装完成后使用 git clone https://gitee.com/n…

应用案例 | 冷藏集装箱基于云的WiFi无线温度监测系统COMET Cloud

一、集装箱的作用和分类 集装箱运输是国际贸易货物多式联运过程中的重要运输方式。由于集装箱运输具有标准化高、密封性好&#xff0c;破损率低、集约化、规模化、班轮化、成本低、质量好等优点&#xff0c;大大提高了货物运输的安全和效率。 集装箱种类很多&#xff0c;按所…

C++类基本常识

文章目录 一、类的默认方法二、类的成员变量初始化1 类的成员变量有三种初始化方法&#xff1a;2 成员变量初始化顺序3 const和static的初始化 三、C内存区域四、const和static 一、类的默认方法 C的类都会有8个默认方法 默认构造函数默认拷贝构造函数默认析构函数默认重载赋…