蓝桥杯— —小明的背包问题

news2025/1/10 0:19:29

小明的背包问题

小明的背包1 — — (01背包)

友情链接:小明的背包1

题目:

请添加图片描述

输入样例:

5 20
1 6
2 5
3 8
5 15
3 3 

输出样例:

37

思路:

对于01背包问题,其中一个重要的条件是每一种物品只有一个,因为在有n个物品v个容量的情况下的最大价值可以由它的子问题n - 1个物品v个容量的最大价值转化而来,因此我们可以利用动态规划的思想进行求解。

我们这样定义dp数组:我们令dp数组的第一维表示每一个物品,dp数组的第二维表示背包的容量。如题目给出的样例,(一共有5个物品,背包的容量为20)我们可以得到如下的dp数组:

01234567891011121314151617181920
0
1
2
3
4
5

对于第二维(即第一行数字)表示的是背包的容量,对于第一维(即第一列数字)表示的是物品的个数,背包的容量和物品的个数都是隐式存在的,并不是一个值,在程序中体现为下标(或索引)。

初始化dp数组:

对于背包容量为0的情况,我们能放入的物品的个数为0个,因此初始化dp数组的第一列的值为0。对于物品个数为0的情况,能放入背包的物品的个数也为0个,因此我们初始化dp数组的第一行的值为0

01234567891011121314151617181920
0000000000000000000000
10
20
30
40
50

递推公式:

对于每一行,即每一个物品来讲,如果当前的容量不能放入该物品,那么只能放入前面的物品,即当前容量能放入前面物品的最大价值,公式为:dp[i][j] = dp[i - 1][j],如果当前的容量能放入该物品,那么就尝试放入该物品,如果放入该物品后的价值更小,就不放入该物品,其值等于没有该物品的情况下当前背包的容量的最大价值,如果放入该物品后价值更大,就放入该物品。对应的公式为dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - w[i] + v[i]]),对于公式dp[i - 1][j - w[i] + v[i]]的理解是,首先每一个物品都是1个,因此要从之前的物品开始减去当前物品的体积(相当于取出一些物品,腾出恰好的空间,得到在背包容量为j - w[i]的情况下的最大价值),然后再放入当前的物品,得到放入当前物品后的价值。公式max(dp[i - 1][j], dp[i - 1][j - w[i] + v[i]])的意义是:对于第i件物品,可以放或者不放,具体取值我哪一种情况的价值更大。

代码:

// 01背包问题
#include<iostream>
#include<vector>
using namespace std;

int solve(){
	int n,v;cin>>n>>v;   // 物品数量和背包容量
	vector<int> value(n + 1, 0);
	vector<int> weight(n + 1, 0); 
	for(int i = 1;i <= n;i ++){
		
		cin>>weight[i];
		cin>>value[i];
	}
	// 进行动态求解
	vector<vector<int>> dp(n + 1, vector<int>(v + 1, 0));
	dp[0][0] = 0;
	for(int i = 1;i <= n;i ++){
		dp[i][0] = 0;
	}
	for(int j = 1;j <= v;j ++){
		dp[0][j] = 0;
	}
	// 递推
	for(int i = 1;i <= n;i ++){  // 每一个物品 
		for(int j = 1;j <= v;j ++){  // 背包容量 
			if(j >= weight[i]){
				dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
			}else{
				dp[i][j] = dp[i - 1][j];   // 不用在和dp[i][j - 1]进行比较了,与完全背包原因一致 
			}
		}
	}
	cout<<dp[n][v]<<endl;
	return 0;
}

int main(){
	ios::sync_with_stdio(0);
	cin.tie(0); 
	int t = 1;
	while(t--){
		solve();
	}
	return 0;
}

在这里插入图片描述

小明的背包2 — — (完全背包)

友情链接:小明的背包2

题目:

在这里插入图片描述

输入样例:

5 20
1 6
2 5
3 8
5 15
3 3 

输出样例:

120

思路:

多重背包问题01背包问题的区别在于,多重背包的每一种物品都可以有无限多个,因此我们只需要再递推公式上进行略微修改即可。

我们定义一个二维的dp数组,其含义与01背包定义的dp数组一样,第一维表示的是物品的种类,第二维表示的是背包的容量。

对于给出的输入样例,可以建立一下的dp数组。

01234567891011121314151617181920
0
1
2
3
4
5

定义边界:
背包容量为0和物品种类为0对应的价值都是0,因此我们要将背包容量为0的一列以及物品种类为0的一行初始化为0

01234567891011121314151617181920
0000000000000000000000
10
20
30
40
50

递推公式:

如果当前的容量不能放下该物品就继承自上一个物品再当前容量的dp值,对应的公式:dp[i][j] = dp[i - 1][j],可能有些小伙伴会有疑问,为什么不继承为max(dp[i - 1][j], dp[i][j - 1])呢?原因是:对于当前物品而言,如果不能放入,那么前一个容量自然也不能放入,依次类推到容量为0的情况,可以知道从0到当前情况每一个值都继承自当前容量的上一个物品的值,对于上一个物品而言,其值也是随着容量的增加而呈现出非严格单调递增的。所以使用公式:max(dp[i - 1][j], dp[i][j - 1])是没有意义的,当然最后的结果也是正确的,我们没有必要再进行一次额外的判断了。

如果当前的容量能够放下该物品,就对应两种动作:放或不放,如果放的话就在当前容量的基础上减去该物品的体积,然后加上该物品的价值,如果不放就取上一个物品对应当前容量的价值,公式为:dp[i][j] = max(dp[i - 1][j], dp[i][j - w[i]] + v[i]),这里与01背包不同的是dp[i][j - w[i]] + v[i]原因就在于完全背包问题可以对某一种物品放无限次,01背包只能对某一种物品放一次。

代码:

// 完全背包
#include<iostream>
#include<vector>
using namespace std;


int solve(){
	int n,v;cin>>n>>v;
	vector<int> value(n + 1, 0);
	vector<int> weight(n + 1, 0);
	for(int i = 1;i <= n;i ++){
		cin>>weight[i];
		cin>>value[i];
	}
	vector<vector<int>> dp(n + 1, vector<int>(v + 1, 0));
	for(int i = 1;i <= n;i ++){
		for(int j = 1;j <= v;j ++){
			if(j >= weight[i]){
				dp[i][j] = max(dp[i - 1][j], dp[i][j - weight[i]] + value[i]);
			}else{
				dp[i][j] = dp[i - 1][j];  // 不用在和 dp[i][j - 1] 进行比较了,因为如果放不下改为物品,那么之前的容量一定是取自上一个物品在当前容量的最大价值 
			}
		}
	}
	cout<<dp[n][v]<<endl;
	
	return 0;
}

int main(){
	ios::sync_with_stdio(0); 
	cin.tie(0);
	int t = 1;
	while(t--){
		solve();
	}
	return 0;
} 

在这里插入图片描述


持续更新中…

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

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

相关文章

git查看单独某一个文件的历史修改记录

git查看单独某一个文件的历史修改记录 git log -p 文件具体路径 注意&#xff0c;Windows下默认文件路径分隔符是 \&#xff0c;在git bash 里面需要改成 /。 git基于change代码修改与提交_git change-CSDN博客文章浏览阅读361次。git cherry-pick&#xff1a;复制多个提交comm…

2023全国青少年信息素养大赛总决赛C++小学组真题

2023 全国青少年信息素养大赛总决赛C小学组真题 第一题 给定一个五位数x&#xff0c;你需要重复做以下操作: 把数的各个数位进行由大到小排序和由小到大排序&#xff0c;得到的最大值和最小值&#xff0c;进行求差后作为新的x。 可以证明&#xff0c;在经过有限次操作后&…

代码随想录算法训练营33期 第三十一天(补29) | 491. 非递减子序列、46. 全排列、47. 全排列 II

491. 非递减子序列 class Solution { public:vector<int> path;vector<vector<int>> result;void BackTracking(vector<int>& nums, int index){if(path.size()>2){result.push_back(path);}unordered_set<int> usedSet;for (int iindex…

爬取日本常用汉字秘籍

前言 昨天投简历时遇到了这样的一个笔试。本以为会是数据结构算法之类的没想到直接发了一个word直接提需求&#xff0c;感觉挺有意思就写了这篇文章&#xff0c;感兴趣的朋友可以看看。 1. 网页内容解析 首先&#xff0c;我们通过请求网页获取到日本常用汉字的链接列表。然后…

多线程java

多线程的创建 前两种方法无法返回直接结果,而有的线程执行完毕后需要返回结果 方式一:java是通过java.lang.Thread类的对象来代表线程的 启动线程必须调用strat方法,不是调用run方法不要把主线程任务放在启动子线程之前 //1.让子类继承Thread线程类 public class MyThread …

逻辑卷和磁盘配额

文章目录 一、逻辑卷二、磁盘配额 一、逻辑卷 为什么会出现技术&#xff1f; 分区的缺点&#xff1a; 没有备份功能无法扩容性能取决于硬盘本身 相关概念 LVM 是 Logical Volume Manager 的简称&#xff0c;译为中文就是逻辑卷管理。它是 Linux 下对硬盘分区的一种管理机制。…

HarmonyOS开发学习:【DevEco Device Tool 安装配置(问题全解)】

本文介绍如何在Windows主机上安装DevEco Device Tool工具。 坑点总结&#xff1a; 国内部分网络环境下&#xff0c;安装npm包可能会很慢或者超时&#xff0c;推荐使用国内npm源&#xff08;如淘宝源、华为源等&#xff09;&#xff1b;serialport这个npm包安装的过程中需要编…

STC8H8K64U 库函数学习笔记 —— GPIO 点灯

STC8H8K64U 库函数学习笔记 —— GPIO 点灯 环境说明&#xff1a; 芯片&#xff1a;STC8H8K64U 软件&#xff1a; KeilC51 μVersion V5.38.00STCAI-ISP (V6.94) 不得不说&#xff0c;Keil 是我用过的 IDE 中&#xff0c;最让人头疼的事情&#xff0c;写代码就像是在记事本里编…

【进阶篇】三、Java Agent实现自定义Arthas工具

文章目录 0、客户端代码1、JMX2、实现&#xff1a;查看内存使用情况3、实现&#xff1a;查看直接内存4、实现&#xff1a;生成堆内存快照5、实现&#xff1a;打印栈信息6、实现&#xff1a;打印类加载器的信息7、实现&#xff1a;打印类的源码8、需求&#xff1a;打印方法的耗时…

OpenHarmony开发学习:【源码下载和编译】

本文介绍了如何下载鸿蒙系统源码&#xff0c;如何一次性配置可以编译三个目标平台&#xff08;Hi3516&#xff0c;Hi3518和Hi3861&#xff09;的编译环境&#xff0c;以及如何将源码编译为三个目标平台的二进制文件。 坑点总结&#xff1a; 下载源码基本上没有太多坑&#xff…

HarmonyOS开发实例:【菜单app】

简介 分布式菜单demo 模拟的是多人聚餐点菜的场景&#xff0c;不需要扫码关注公众号等一系列操作&#xff0c;通过分布式数据库可以方便每个人可及时查看到订单详情&#xff0c;数量&#xff0c;总额等&#xff1b;效果如下 demo效果 工程目录 完整的项目结构目录如下 ├…

2024年DeFi的四大主导趋势:Restaking、Layer3、AI和DePin

DeFi&#xff08;去中心化金融&#xff09;行业在2024年将继续呈现快速增长的势头&#xff0c;驱动这一增长的主要因素将是四大主导趋势&#xff1a;Restaking、Layer3、AI和DePin。这些趋势将推动DeFi生态系统的发展&#xff0c;为用户提供更多的机会和创新。 趋势1&#xff…

雨云:不只是一阵清风,更是一场暴雨的力量

引言 在网络时代&#xff0c;服务器是任何在线业务的核心。无论你是运营一家小型博客还是承载着数百万用户的大型电商平台&#xff0c;都需要一个稳定、高效的服务器来支持你的业务。然而&#xff0c;在众多服务器提供商中&#xff0c;有一家备受推崇&#xff0c;那就是雨云。 …

【C语言】双向链表详解

文章目录 关于双向链表双向链表的初始化双向链表的打印双向链表方法调用 - 尾删为例双向链表的查找 - 指定位置之后插入为例双向链表结束 - 链表的销毁小结及整体代码实现 关于双向链表 首先链表有8种基本分法 其中在笔者之前文章种详细介绍的 单链表 是不带头单项不循环链表…

快速解锁3D Web渲染引擎HOOPS Communicator轻量化技术

在当今数字化时代&#xff0c;三维模型的使用已经成为许多行业中不可或缺的一部分。然而&#xff0c;随着模型复杂性的增加和数据量的膨胀&#xff0c;如何在Web浏览器中高效加载和渲染这些模型成为了一个挑战。慧都3D Web渲染引擎HOOPS Communicator通过其先进的轻量化技术&am…

测试过程和测试生命周期

软件测试过程是一系列有计划、有组织的活动&#xff0c;旨在识别和解决软件产品中的问题。这个过程通常包括多个阶段&#xff0c;每个阶段都有其特定的目标和方法。 需求分析&#xff1a; 分析软件需求和测试需求&#xff0c;确定测试的目标和范围。理解用户需求和业务目标&…

MM-Grounding-DINO的训练推理(待更新)

1、简单介绍 继前面发布的 GroundingDino 和 Open-GroundingDino的推理 和 Open-GroundingDino的训练实现&#xff0c;作为 GroundingDino延续性的文本检测网络 MM-Grounding-DINO 也发布了较详细的 训练和推理实现教程&#xff0c;而且操作性很强。作为学习内容&#xff0c;也…

我对硬技能与软技能的认知

今天看到一个很有意思的一段话&#xff0c;假设一个人的技能有两种&#xff0c;分别是&#xff1a;硬技能和软技能。 硬技能通常指的是与工作直接相关的、可以通过教育和培训获得的技能&#xff0c;如编程语言、会计知识等,这些技能往往有明确的衡量标准&#xff0c;容易通过考…

java 将 json 数据转为 java 中的对象

一、准备 json 数据 {"name": "mike","age": 17,"gender": 1,"subject": ["math","english"] }二、对应的java对象 package com.demo.controller;import lombok.Data; import java.util.List;Data pu…

鸿蒙TypeScript学习第13天:【元组】

1、TypeScript 元组 我们知道数组中元素的数据类型都一般是相同的&#xff08;any[] 类型的数组可以不同&#xff09;&#xff0c;如果存储的元素数据类型不同&#xff0c;则需要使用元组。参考文档&#xff1a;qr23.cn/AKFP8k 元组中允许存储不同类型的元素&#xff0c;元组…