C++算法初级11——01背包问题(动态规划2)
C++算法初级11——01背包问题(动态规划2)
文章目录
- C++算法初级11——01背包问题(动态规划2)
- 问题引入
- 0-1背包问题分析
- 0-1背包问题的形式化分析
- 优化
问题引入
辰辰采药
辰辰是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师。为此,他想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难题。医师把他带到一个到处都是草药的山洞里对他说:“孩子,这个山洞里有一些不同的草药,采每一株都需要一些时间,每一株也有它自身的价值。我会给你一段时间,在这段时间里,你可以采到一些草药。如果你是一个聪明的孩子,你应该可以让采到的草药的总价值最大。”
如果你是辰辰,你能完成这个任务吗?
辰辰采药在算法中属于一种很经典的0-1背包问题。更一般的,这种问题可以转化为:
给定n个物品,每个物体有个体积v i和一个价值p i
现有一个容量为V的背包,请问如何选择物品装入背包,使得获得的总价值最大?
0-1背包问题分析
0-1背包问题描述:给定n个物品,每个物体有个体积v i和一个价值p i
现有一个容量为V的背包,请问如何选择物品装入背包,使得获得的总价值最大?
基本思路
考虑到现在我们能做的决策,只有对于每个物品的“选”与“不选”。所以,这个问题就是
- 以“将每一个物品依次放入背包”划分不同阶段
- 而对于每个物品的“选与不选”就是不同决策
考虑到所有的放置前i个物品的方案数可以分为两类:
- 一个是放第i个物品,
- 一个是不放第i个物品
所以下面我们分这两种情况来讨论。因为在决策的过程中,变化的是当前所在的阶段,以及容量的剩余大小。
所以,我们维护一个二维状态f[i,j], 来表示前i个物品,放到体积为j的背包里,可以得到的最大价值。
首先,考虑容量为任意值j时,将前i个物品放入背包的情况。
所以,状态转移方程为 f [ i ] [ j ] = m a x { f [ i − 1 , j ] , p [ i ] + f [ i − 1 ] [ j − v [ i ] } f[i][j]=max\{f[i-1,j],p[i]+f[i-1][j-v[i]\} f[i][j]=max{f[i−1,j],p[i]+f[i−1][j−v[i]}
0-1背包问题的形式化分析
使用动态规划解决问题,需要明确状态设计、转移方程、初始状态和转移方向四个方面。
那现在,让我们来明确一下该0-1背包问题中的动态规划四要素:
- 状态:
用f[i][j]表示前i个物品,放在空间为j的背包里,能获得的最大收益。 - 转移方程:
因为每一个阶段有至多两种选择,所以需要分别计算两种选择的收益后取较大值。
f[i][j] = f[i - 1][j] // j < v[i],表示装不下第i个物品
f[i][j] = max(f[i - 1][j], f[i - 1][j - v[i]] + p[i]); // otherwise
- 初始状态:
在一个物品都没放的时候,无论背包大小多少,总价值都是0,即
f[0][j] = 0 // 0 <= j <= V
- 转移方向:
观察转移方程,发现要想保证等式右边的状态一定比左边的状态先算出来,只需要保证i从小到大计算即可。
最终该问题的答案就是f[n,V]。这样,0-1背包问题就可以使用动态规划来解决~
代码
# include <bits/stdc++.h>
using namespace std;# define N 1002
int n=3;
int V = 70;
vector<int> v = {0,71,69,1};//体积
vector<int> p ={0,100,1,2};//价值
// 第0位,置为0,不参与计算,便于与后面的下标进行统一
int f[N][N];int main()
{for(int j=0;j<=V;j++)f[0][j]=0;for(int i=1;i<=n;i++){if(v[i]>V)continue;for(int j=0;j<=V;j++){if(j<v[i])f[i][j]=f[i-1][j];elsef[i][j]=max(f[i-1][j],f[i-1][j-v[i]]+p[i]);}}cout<<f[n][V]<<endl;
}
动态规划的主要工作:就是算出不同状态下的结果,然后用相应维数的数组保存。
所以,整个动态规划的过程就是一个”填表“的过程。
优化
滚动数组优化
因为整个动态规划的过程就是一个填表的过程,如下图:
而在本题中,填表的顺序就是:填完上一行,然后填下一行。而且我们发现,下一行的状态,只会用到上一行的状态来转移。所以,当我们在计算第i行时,其实前i−2行的状态就都没必要保留了。所以,我们可以用一种类似于”踩石头过河“的思想。
试想如果我们有一些石头,想利用这些石头过河。
如果石头的数量很多,那么最方便的方法就是用这些石头铺一道石头路,这样我们就可以顺利过河。这就相当于我们可以开很充足的数组,然后把计算的每个阶段都存在数组里。
但如果我们只有两块石头,就过不了河了吗?不是的。我们可以用下图的方法一边走一边挪动石头,这样也可以顺利过河。
在空间优化的方法中,有一种很常见就是利用过河的思想。这种方法叫做滚动数组。在整个算法过程中,我们只用2×V的数组f[2][V]来记录状态。其中,所有奇数行的状态填入f[1][j]中,所有偶数行的状态填入f[0][j]中,如下图
# include <bits/stdc++.h>
using namespace std;# define N 1002
int n=3;
int V = 70;
vector<int> v = {0,71,69,1};//体积
vector<int> p ={0,100,1,2};//价值
// 第0位,置为0,不参与计算,便于与后面的下标进行统一
int f[2][N];//f[i][j]表示前i个物品,体积为j的最大价值int main()
{for(int i=1;i<=n;i++){for(int j=0;j<=V;j++){if(j<v[i])f[i&1][j] = f[(i-1)&1][j];elsef[i&1][j] = max(f[(i-1)&1][j],f[(i-1)&1][j-v[i]]+p[i]);}}cout<<f[n&1][V]<<endl;return 0;
}
算法优化2 —— 优化到一维数组
那么我们可不可以再进一步优化空间,使得只用一个一维数组就能解决整个问题了呢?
想到之前“踩石头过河”的类比,我们可能会觉得不太可能。但是如果我们进一步分析整个表的填写,如下图:
会发现下一行的某个状态,正好是由它上面的元素,以及左上方的某个元素转移而来。所以我们需要保证当计算黄色状态时上面两个绿色状态没有被覆盖掉。所以,当我们计算第i行时,完全可以将j从大到小枚举,这样在计算状态f(i,j)之前,数组f[j]中存储的是状态f[i−1,j],更新完以后,
f[j]中存的状态就是f[i,j]了。如下图:
# include <bits/stdc++.h>
using namespace std;# define N 1002
int n=3;
int V = 70;
vector<int> v = {0,71,69,1};//体积
vector<int> p ={0,100,1,2};//价值
// 第0位,置为0,不参与计算,便于与后面的下标进行统一
int f[N];int main()
{for(int i=1;i<=n;i++){for(int j=V;j>=v[i];j--){f[j] = max(f[j],f[j-v[i]]+p[i]);}}cout<<f[V]<<endl;return 0;
}
相关文章:

C++算法初级11——01背包问题(动态规划2)
C算法初级11——01背包问题(动态规划2) 文章目录 C算法初级11——01背包问题(动态规划2)问题引入0-1背包问题分析0-1背包问题的形式化分析优化 问题引入 辰辰采药 辰辰是个天资聪颖的孩子,他的梦想是成为世界上最伟大…...
Python 库大全(下)
格式化输出 模块 reprlib 提供了一份定制的 repr(),用于简洁 地展示各种大的或者多层嵌套的容器变量: >>> import reprlib >>> reprlib.repr(set(\supercalifragilisticexpialidocious\)) "{\a\, \c\, \d\, \e\, \f\, \g\, ...…...

如何用链表实现LRU缓存淘汰算法
链表学习 一、 缓存1.1缓存介绍1.2 缓存策略 二、链表结构2.1 单链表2.2 循环链表2.3 双向链表2.4 双向循环链表2.5 链表与数组性能对比 三、如何基于链表实现LRU缓存淘汰算法 一、 缓存 1.1缓存介绍 缓存是一种提高数据读取性能的技术,在硬件设计、软件开发中都有…...
【01】数据结构与算法基础-数据、数据元素、数据项和数据对象 | 数据类型和抽象数据类型 | 抽象数据类型的表示和C++实现
目录) 0.数据结构的研究内容1.数据、数据元素、数据项和数据对象1.1数据1.2数据元素(Data element)和数据项1.3数据项1.4数据对象1.5数据结构(Data Structure)1.6逻辑结构的种类1.7存储结构的种类2.数据类型和抽象数据类型2.1数据类型(Data Type)2.2抽象数据类型(Abstract …...
PHP匿名类的使用场景有哪些?PHP匿名类怎么用?有什么好处?PHP匿名类如何在运行时动态生成?
以下是一些使用匿名类的场景: 2. 简单的工厂模式:当需要在运行时动态创建一些简单的对象时,可以使用匿名类替代创建不必要的类定义和文件。 function createGreeter($name) {return new class($name) {private $name;public function __cons…...

【并发基础】一篇文章带你彻底搞懂Java线程中断的底层原理——interrupt()、interrupted()、isInterrupted()
目录 〇、Java线程中断与阻塞的区别 0.1 线程中断 0.2 线程阻塞 一、线程的中断 二、中断方法 2.1 void interrupt() 2.1.1 可中断的阻塞 2.1.2 不可中断的阻塞 2.1.3 实践案例 2.2 boolean isInterrupted() 2.3 boolean interrupted() 2.4 代码案例 三、源码分析…...

【c语言】函数的数据传递原理 | 数组传入函数方法
创作不易,本篇文章如果帮助到了你,还请点赞支持一下♡>𖥦<)!! 主页专栏有更多知识,如有疑问欢迎大家指正讨论,共同进步! 给大家跳段街舞感谢支持!ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ…...
vue3源码(3)——computed
Vue3中的computed底层源码主要是通过使用Proxy对象来实现的。下面是对Vue3中computed底层源码的详细解读: 在Vue3中,computed的实现是通过使用createComputed函数来创建的。createComputed函数接收两个参数:getter和setter。 在createComput…...

数学建模第七天:数学建模算法篇之插值及MATLAB实现
目录 一、前言 1、引例 2、拟合定义 3、拟合与插值的关系 二、拟合 1、线性最小二乘法求解 ①思路 ②解法 2、MATLAB对线性最小二乘拟合的实现 ①函数说明 ②求解例题 3、MATLAB实现非线性曲线拟合 ①lsqcurvefit函数 ②代码求解 4、MATLAB实现非线性最小二乘拟…...

RUST 每日一省:生命周期作用域
生命周期 一个变量的生命周期就是它从创建到销毁的整个过程。 作用域 我们声明的每个变量都有作用域。作用域其实是变量和值存在的环境。作用域是由一对花括号表示的。例如,使用块表达式会创建一个作用域,即任何以花括号开头和结尾的表达式。此…...

【过程8】——能量守恒视角总结感受
一、背景 另一个角度的看到,观望着过程中自己曾经类似的经历(小舅子的工作)。 时间久了,经历多了,感悟会更加的充实;最近自己对于人在维持能量的过程中也有很多的感悟,一并做一下总结 二、过程 1.人为什么天性不愿意…...

kong(4):限流配置
Kong 提供了 Rate Limiting 插件,实现对请求的限流功能,避免过大的请求量过大,将后端服务打挂。 Rate Limiting 支持秒/分/小时/日/月/年多种时间维度的限流,并且可以组合使用。例如说:限制每秒最 多 100 次请求&…...

人脸识别 Face Recognition 入门
人脸识别 Face Recognition 入门概述 总述传统特征方法深度学习方法损失函数改进基于欧几里德和距离的损失基于角度/余弦边距的损失SoftMax 损失及其变体 一级标题二级标题二级标题二级标题 找论文搭配 Sci-Hub 食用更佳 💪 Sci-Hub 实时更新 : https://tool.yovisu…...

【AI绘画】Midjourney的使用及程序示例
Midjourney 1.背景2.Midjourney的原理3.Midjourney的使用方法4.Midjourney的示例代码 1.背景 Midjourney 是一款基于深度学习的图像转换工具,其可以将一张图像转换成具有不同风格的图像,例如将一张照片转换成卡通风格的图像。Midjourney 基于 TensorFlow…...

无公网IP?教你在外远程访问本地wamp服务器「内网穿透」
目录 前言 1.Wamp服务器搭建 1.1 Wamp下载和安装 1.2 Wamp网页测试 2. Cpolar内网穿透的安装和注册 2.1 本地网页发布 2.2 Cpolar云端设置 2.3 Cpolar本地设置 3. 公网访问测试 4. 结语 前言 软件技术的发展日新月异,各种能方便我们生活、工作和娱乐的新…...
leetcode 628. 三个数的最大乘积
题目描述解题思路执行结果 leetcode 628. 三个数的最大乘积 题目描述 三个数的最大乘积 给你一个整型数组 nums ,在数组中找出由三个数组成的最大乘积,并输出这个乘积。 示例 1: 输入:nums [1,2,3] 输出:6 示例 2&…...

fork函数如何创建进程,exit/_exit函数如何使进程终止的详细分析与代码实现
🎊【进程通信与并发】专题正在持续更新中,进程,线程,IPC,线程池等的创建原理与运用✨,欢迎大家前往订阅本专题,获取更多详细信息哦🎏🎏🎏 🪔本系列…...

重置电脑时提示“缺少所需的驱动器分区”怎么办?
当您启动Windows 10电脑并收到“您的电脑/设备需修复”这个消息提示时,您会马上尝试修复电脑,如果您这样做了,您可能会收到一个“安装Windows的驱动器已被锁定”的信息。如果您尝试重置您的电脑,您可能会收到一条提示,…...

在KylinV10安装Dm8
前言 因为近期,业外和几个朋友想搞点有趣的项目玩玩,既然不以盈利为主,就> 主推国产化,所以这篇记录一下,我在KylinV10安装dm8.最近真的很忙,要负责专研一下国产化工具开发的事,还要负责tb级…...
「SQL面试题库」 No_46 交换工资
🍅 1、专栏介绍 「SQL面试题库」是由 不是西红柿 发起,全员免费参与的SQL学习活动。我每天发布1道SQL面试真题,从简单到困难,涵盖所有SQL知识点,我敢保证只要做完这100道题,不仅能轻松搞定面试࿰…...

idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...

Day131 | 灵神 | 回溯算法 | 子集型 子集
Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣(LeetCode) 思路: 笔者写过很多次这道题了,不想写题解了,大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...

【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...

ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)
上一章用到了V2 的概念,其实 Fiori当中还有 V4,咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务),代理中间件(ui5-middleware-simpleproxy)-CSDN博客…...
Python ROS2【机器人中间件框架】 简介
销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...