蓝桥杯DP算法——背包问题(C++)
目录
一、01背包问题
二、完全背包问题
三、多重背包问题
四、多重背包问题(优化版)
五、分组背包问题
一、01背包问题
01背包问题就是有N件物品,一个空间大小为V的背包,每个物品只能使用一次,使得背包中所装物品的价值总和最大。
如图所示使用一个二维数组来存放从前i个物品中取,总体积不超过j的包中价值最大值。
根据图二所示,我们可以将每次dp到的情况分为两种,一种是选择第 i 件物品,另一种是不选择第 i 件物品。
- (不含 i )就是从0~i-1中选择体积不超过 j 的物品,也就是
- (含 i )即从 1 ~ i 中选,包含 i,且总体积不超过 j。可以先把第 i 个物品拿出来,即从第 1 ~ i-1中选,且总体积不超过 j-v[i],也就是
最终:f[ i ][ j ] = max(f[ i-1 ][ j ], f[i-1][j-v[ i ]] +w[ i ]
例题:https://www.acwing.com/problem/content/2/
朴素做法:
#include<iostream>
using namespace std;
const int N=1010;
int v[N],w[N];
int f[N][N];int main()
{int n,m;cin>>n>>m;for(int i =1;i<=n;i++) cin>>v[i]>>w[i];for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){f[i][j]=f[i-1][j];if(j>=v[i])//可以装的下{f[i][j]=max(f[i][j],f[i-1][j-v[i]]+w[i]);}}}cout<<f[n][m];return 0;
}
优化:
f[i] 只用到了 f[i-1] 这一层,即 f[i-2] 到 f[0] 对 f[i] 是没有用的,所以第二层循环可以直接从 v[i] 开始
for (int i = 1; i <= n; i++) {for (int j = v[i]; j <= m; j++) {f[i][j] = max(f[i][j], f[i - 1][j - v[i]] + w[i]);}
}
从二维优化成一维(空间优化)
如果直接删除掉 f[i] 这一维即
f[j] = max(f[j], f[j-v[i]] + w[i]);
但是这样直接删掉是错误,因为j是递增的。
原式:f[i][j] = max(f[i][j], f[i - 1][j - v[i]] + w[i]);
改成一维:f[j] = max(f[j], f[j - v[i]] + w[i]);
由于 f[i][] 只跟上一状态(f[i - 1][])有关 上面两个式子 :这一状态(左) = 上一状态(右)
即 f[i][j] 是由 f[i - 1][j - v[i]] 推出来的 现在进行空间优化,那么必须要保证 f[j] 要由 f[j - v[i]] 推出来的。
如果j层循环是递增的,则相当于 f[i][j] 变得是由 f[i][j - v[i]] 推出来的, 而不是 f[i - 1][j - v[i]] 推出来的。
优化后代码:
#include<iostream>
using namespace std;
const int N=1010;
int v[N],w[N];
int f[N];int main()
{int n,m;cin>>n>>m;for(int i =1;i<=n;i++) cin>>v[i]>>w[i];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];return 0;
}
二、完全背包问题
完全背包不同于01背包的是,每件物品都是无限使用的。
如图所示,与01背包相似的是每次选择0,1,2,3,4,5,....k个
不选时仍是 f[ i-1][ j ]
选择k件时是 f[ i-1][ j-k*v[i]] +k*w[i]
也就是:
f[ i-1][ j-k*v[i]] +k*w[i]
例题:https://www.acwing.com/problem/content/3/
朴素写法:
#include<iostream>
using namespace std;const int N=1010;
int n,m;
int v[N],w[N],f[N][N];int main()
{cin>>n>>m;for(int i=i;i<=n;i++) scanf("%d%d",&v[i],&w[i]);for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){for(int k=0;k*v[i]<=j;k++){f[i][j]=max(f[i][j],f[i-1][j-k*v[i]]+w[i]*k);}}}cout<<f[n][m];return 0;
}
优化:
在对完全背包问题优化时,我们由图公式可知f[i][j]可以简化为max(f[i-1][j],f[i][j-v]+w)
优化后代码:
#include <iostream>
#include <algorithm>using namespace std;const int N=1010;
int f[N];
int v[N],w[N];
int n,m;
int main()
{cin>>n>>m;for(int i=1;i<=n;i++) cin>>v[i]>>w[i];for(int i=1;i<=n;i++){for(int j=v[i];j<=m;j++){f[j]=max(f[j],f[j-v[i]]+w[i]);}}cout<<f[m];return 0;
}
三、多重背包问题
多重背包问题相较于之前的问题就是每个物品是有限s个。
例题:https://www.acwing.com/problem/content/4/
#include<iostream>
using namespace std;
const int N=110;int n,m;
int s[N],v[N],w[N];
int f[N][N];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 j=0;j<=m;j++){for(int k=0;k<=s[i]&&j>=(k*v[i]);k++){f[i][j]=max(f[i][j],f[i-1][j-v[i]*k]+w[i]*k);}}}cout<<f[n][m];return 0;
}
四、多重背包问题(优化版)
首先我们以之前完全背包问题的优化方法尝试使用另一个表达式来代替,但是结果如图所示,不是很好解决。
二进制法优化:二进制优化的方法在于使用二进制的表示方式来代替每个物品的个数,当某件物品的个数很多的时候无需从1遍历循环到n,可以将其分解成个位权来表示。
为了方便理解举个例子:
如果要拿1001次苹果,传统就是要拿1001次;二进制的思维,就是拿7个箱子就行(分别是装有512、256、128、64、32、8、1个苹果的这7个箱子),这样一来,1001次操作就变成7次操作就行了。
但是要注意的一点是如果某件物品的个数不是二次幂减一,就将前一位的值与s差值记为下一个位权。这样就可以表示0~s之内的所有数了。
然后就将问题分解成为了,01背包问题。
例题:https://www.acwing.com/problem/content/5/
#include<iostream>
using namespace std;const int N=11010,M=2010;
int v[N],w[N];
int f[N];int main()
{int n,m;cin>>n>>m;int cnt=0;while(n--)//初始化v[] w[]{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];return 0;
}
五、分组背包问题
分组背包问题的不同于之前背包问题的地方在于分组背包是将物品分成几组,然后再在每组里面选择一个物品,并且每组只能选择一个物品。
这里的dp状态计算与之前的也有所不同,这里表示的是第i组选哪一个,f[i-1][j]是表示不选择这一组的物品,f[i-1][j-v[i,k]]+w[i,k]表示的是这一组中选择哪一个。
例题: https://www.acwing.com/problem/content/9/
#include<iostream>
using namespace std;const int N=110;
int n,m;
int s[N],v[N][N],w[N][N];
int f[N];int main()
{cin>>n>>m;for(int i=1;i<=n;i++){cin>>s[i];for(int j=1;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];return 0;
}
相关文章:

蓝桥杯DP算法——背包问题(C++)
目录 一、01背包问题 二、完全背包问题 三、多重背包问题 四、多重背包问题(优化版) 五、分组背包问题 一、01背包问题 01背包问题就是有N件物品,一个空间大小为V的背包,每个物品只能使用一次,使得背包中所装物品…...
【LeetCode+JavaGuide打卡】Day22|235. 二叉搜索树的最近公共祖先、701.二叉搜索树中的插入操作、450.删除二叉搜索树中的节点
学习目标: 235. 二叉搜索树的最近公共祖先 701.二叉搜索树中的插入操作 450.删除二叉搜索树中的节点 学习内容: 235. 二叉搜索树的最近公共祖先 题目链接&&文章讲解 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最…...
Stable Diffusion WebUI 界面介绍
本文收录于《AI绘画从入门到精通》专栏,专栏总目录:点这里。 大家好,我是水滴~~ 本文主要对 Stable Diffusion WebUI 的界面进行简单的介绍,让你对该 WebUI 有个大致的了解,为后面的深入学习打下一个基础。主要内容包括:Stable Diffusion 模型(Stable Diffusion checkp…...

Cocos2dx-lua ScrollView[一]基础篇
一.ScrollView概述 cocos游戏中ScrollView控件大量使用,95%以上的项目都会使用ScrollView,个别游戏可能全部使用翻页的滑动效果。如果想要精通Cocos的UI开发,精通ScrollView控件非常关键,因此对ScrollView的使用进行总结很有必要。 下文缩写说明:sv = ScrollView, item代…...

QT应用软件【协议篇】周立功CAN接口卡代码示例
文章目录 USBCAN系列CAN接口卡规格参数资料下载QT引用周立功的库安装sdk代码USBCAN系列CAN接口卡 USBCAN系列CAN接口卡兼容USB2.0全速规范,可支持1/2/4/8路CAN接口。采用该接口卡,PC机可通过USB连入CAN网络,进行CAN总线数据采集和处理,主要具备以下几大优势特点: 支持车载…...

JVM对象的创建流程与内存分配
对象的创建流程与内存分配 创建流程对象内存分配方式内存分配安全问题对象内存分配流程【重要】:对象怎样才会进入老年代?重点 案例演示:对象分配过程大对象直接进入老年代02-对象内存分配的过程: 创建流程 加载 验证 解析 准备 初始化 使用 写在 对象内存分配方式 内存分配…...

docker (六)-进阶篇-数据持久化最佳实践MySQL部署
容器的数据挂载通常指的是将宿主机(虚拟机或物理机)上的目录或文件挂载到容器内部 MySQL单节点安装 详情参考docker官网文档 1 创建对应的数据目录、日志目录、配置文件目录(参考二进制安装,需自己建立数据存储目录) mkdir -p /data/mysq…...

力扣题目训练(17)
2024年2月10日力扣题目训练 2024年2月10日力扣题目训练551. 学生出勤记录 I557. 反转字符串中的单词 III559. N 叉树的最大深度241. 为运算表达式设计优先级260. 只出现一次的数字 III126. 单词接龙 II 2024年2月10日力扣题目训练 2024年2月10日第十七天编程训练,今…...
【react】react中和vue中的provide/inject、context写法示例
react写法 在 React 中,provide和inject的功能类似于 Vue.js 中的 provide和inject。它们都是用于跨组件层次传递数据的。 在 React 中,没有内置的 provide 和 inject 函数。但是,你可以使用 React 的 Context 来实现类似的功能。 Context…...
MySQL 的存储引擎(基本介绍)
文章目录 前言MySQL 的存储引擎介绍存储引擎是什么?存储引擎的特性? Innodb 与 Mylsam 的区别行级锁与表级锁是否支持事务是否支持恢复数据是否支持外键是否支持 MVCC 总结 前言 好文章不要错过,前两天跟大家分享的文章 1.MySQL的基础架构 2.SQL语句的…...
Unity3D 实现基于物理引擎的绳子关节解析详解
前言 在游戏开发中,有时候我们需要实现绳子关节效果,比如在射击游戏中射击绳子,或者在平衡游戏中使用绳子作为支撑。本文将详细介绍如何使用Unity3D的物理引擎实现绳子关节效果。 对惹,这里有一个游戏开发交流小组,希…...

C语言二级易忘易错易混知识点(自用)
1.数组名不能自加。 因为数组名实际上是一个指针,指向数组的第一个元素的地址。数组名在编译器中被视为常量,它的值是固定的,不能改变。 要访问数组的不同元素,应该使用数组名加上偏移量的方式来访问。 2.共用体只有最后一次赋值…...

js_三种方法实现深拷贝
深拷贝( 递归 ) 适用于需要完全独立于原始对象的场景,特别是当对象内部有引用类型时,为了避免修改拷贝后的对象影响到原始对象,就需要使用深拷贝。 // 原始对象 const obj { uname: Lily,age: 19,hobby: [乒乓球, 篮球…...
【图论经典题目讲解】CF715B - Complete The Graph
C F 715 B − C o m p l e t e T h e G r a p h \mathrm{CF715B - Complete\ The\ Graph} CF715B−Complete The Graph D e s c r i p t i o n \mathrm{Description} Description 给定一张 n n n 个点, m m m 条边的无向图,点的编号为 0 ∼ n − 1 0\…...
[office] excel中数据汇总的大全教程文字版 #知识分享#经验分享#知识分享
excel中数据汇总的大全教程文字版 我们在excel中对数据清单上的数据进行分析的一种方法是分类汇总。在“数据”菜单上选择“分类汇总”命令,我们可以在数据清单中插入分类汇总行,然后按照选择的方式对数据进行汇总。同时,在插入分类汇总时&am…...
leetcode经典题库(简单)
文章目录 1.两数之和2.反转链表3.合并两个有序列表4.合并两个有序链表5.删除有序数组中的重复项6.从数组中移除元素7. 搜索指定数值在数组中的插入位置8. 数组最后一位加一9. 合并两个有序数组在leetcode上刷了几个和数组相关的简单题,记录在这里。 1.两数之和 给定一个整数…...

python coding with ChatGPT 打卡第21天| 二叉树:最近公共祖先
相关推荐 python coding with ChatGPT 打卡第12天| 二叉树:理论基础 python coding with ChatGPT 打卡第13天| 二叉树的深度优先遍历 python coding with ChatGPT 打卡第14天| 二叉树的广度优先遍历 python coding with ChatGPT 打卡第15天| 二叉树:翻转…...

openGauss学习笔记-224 openGauss性能调优-系统调优-数据库系统参数调优-数据库并发队列参数调优
文章目录 openGauss学习笔记-224 openGauss性能调优-系统调优-数据库系统参数调优-数据库并发队列参数调优224.1 全局并发队列224.2 局部并发队列 openGauss学习笔记-224 openGauss性能调优-系统调优-数据库系统参数调优-数据库并发队列参数调优 数据库提供两种手段进行并发队…...

UE5 C++ 创建可缩放的相机
一.要将相机设置在Pawn类里 1.在MyPawn头文件里,加上摇臂和相机组件 #include "GameFramework/SpringArmComponent.h" #include "Camera/CameraComponent.h" 2.在Pawm里声明SceneComponet,SpringArmComponent,CameraComponent组件…...
Fabric中的溯源方法
背景 在Fabric链码中,我们可以使用PutState方法对一个key的值进行覆盖,当我们再使用GetState查询时是最新的值。如果我们希望找到这个key的修改记录,我们可以使用溯源方法GetHistoryForKey。完整源码链接:https://github.com/hyp…...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...

使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...
QT3D学习笔记——圆台、圆锥
类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体(对象或容器)QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质(定义颜色、反光等)QFirstPersonC…...

人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式
今天是关于AI如何在教学中增强学生的学习体验,我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育,这并非炒作,而是已经发生的巨大变革。教育机构和教育者不能忽视它,试图简单地禁止学生使…...
jmeter聚合报告中参数详解
sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample(样本数) 表示测试中发送的请求数量,即测试执行了多少次请求。 单位,以个或者次数表示。 示例:…...

MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)
macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 🍺 最新版brew安装慢到怀疑人生?别怕,教你轻松起飞! 最近Homebrew更新至最新版,每次执行 brew 命令时都会自动从官方地址 https://formulae.…...

从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障
关键领域软件测试的"安全密码":Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力,从金融交易到交通管控,这些关乎国计民生的关键领域…...
【Elasticsearch】Elasticsearch 在大数据生态圈的地位 实践经验
Elasticsearch 在大数据生态圈的地位 & 实践经验 1.Elasticsearch 的优势1.1 Elasticsearch 解决的核心问题1.1.1 传统方案的短板1.1.2 Elasticsearch 的解决方案 1.2 与大数据组件的对比优势1.3 关键优势技术支撑1.4 Elasticsearch 的竞品1.4.1 全文搜索领域1.4.2 日志分析…...

Sklearn 机器学习 缺失值处理 获取填充失值的统计值
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 使用 Scikit-learn 处理缺失值并提取填充统计信息的完整指南 在机器学习项目中,数据清…...
【Kafka】Kafka从入门到实战:构建高吞吐量分布式消息系统
Kafka从入门到实战:构建高吞吐量分布式消息系统 一、Kafka概述 Apache Kafka是一个分布式流处理平台,最初由LinkedIn开发,后成为Apache顶级项目。它被设计用于高吞吐量、低延迟的消息处理,能够处理来自多个生产者的海量数据,并将这些数据实时传递给消费者。 Kafka核心特…...