背包九讲——背包问题求具体方案
目录
背包问题求具体方案
1. 01 背包问题
题目:12. 背包问题求具体方案 - AcWing题库
算法思路:
代码实现:
2. 多重背包问题
算法思路:
3. 完全背包问题
算法思路:
代码实现:
背包问题第九讲——背包问题求具体方案
背包问题是一类经典的组合优化问题,通常涉及在限定容量的背包中选择物品,以最大化某种价值或利益。问题的一般描述是:有一个背包,其容量为C;有一组物品,每个物品有重量w和价值v。目标是选择一些物品放入背包,使得它们的总重量不超过背包容量,同时总价值最大。
背包问题涉及到了三种基础的背包:01背包、多重背包、完全背包,我们要根据在这几个背包的基础上去计算在获得最大价值的情况下,有几种方案,并输出具体的方案,是求背包问题方案数的进阶版,这个需要打印具体方案了。
背包问题求具体方案
上一篇说了一下背包问题求方案数,下面进行深化一点就是求具体方案了。同上一篇这些问题都是在01背包、多重背包、完全背包基础上演化来的,求具体方案问题会问你一种具体方案(编号序列的字典序最小)或者打印所有具体方案,一般的问题都是问你第一种。若为第二种问法,建议使用C语言的printf进行打印,因为打印所有具体方案,当数据量很大时会有很多输出,使用printf会比cout快一点。根据问题的具体类型,常见的背包问题包括:
1. 01 背包问题
0-1背包问题是指每个物品只有0跟1两种选择即只能选择放或不放,不能分割。给定一组物品,每个物品都有自己的重量和价值,在不超过背包容量的前提下,选择一些物品,使得总价值最大。
题目:12. 背包问题求具体方案 - AcWing题库
有 N 件物品和一个容量是 V 的背包。每件物品只能使用一次。
第 i 件物品的体积是 vi,价值是 wi。
求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出 字典序最小的方案。这里的字典序是指:所选物品的编号所构成的序列。物品的编号范围是 1…N。
输入格式
第一行两个整数,N,V,用空格隔开,分别表示物品数量和背包容积。
接下来有 N 行,每行两个整数 vi,wi,用空格隔开,分别表示第 i 件物品的体积和价值。
输出格式
输出一行,包含若干个用空格隔开的整数,表示最优解中所选物品的编号序列,且该编号序列的字典序最小。
物品编号范围是 1…N。
数据范围
0<N,V≤1000
0<vi,wi≤1000输入样例
4 5 1 2 2 4 3 4 4 6
输出样例:
1 4
算法思路:
题目要求了输出字典序最小,所以尽量靠前去,尽管有不同的方案所获得最大价值一样,但是要考虑字典序最小,所以一定要选前面的,比如选1,3,5和2,3,4所获得的价值一样,但是要选1,3,5,所以后面遍历下标从小到大遍历的。上面说明了如果第一个物品属于最优解的一种,一定要选它,这样问题就转化成了从2~N寻找最优解问题,以此类推。
状态定义f[i][j]表示从第i个物品开始到最后一个物品背包容量为j所获得的最大价值
状态转移:f[i][j]=max(f[i+1][j],f[i+1][j-v[i]]+w[i])
f[i][j]的上一个状态就是从i+1转移过来的,因为我们定义从第i个物品到最后一个物品,第i+1个物品到最后一个之间的数量是不是比第i个物品到最后一个物品少。f[i+1][j]是不选第i个物品,f[i+1][j-v[i]]+w[i]是选第i个物品。因为我要在所有f[i][j]当中选择一个最大值,所以前面我管不管的先初始化为不选,往后如果背包容量大于体积,那我再看看是选了这个物品总价值是否增大,如果增大就更新,不增大就保持原来。这样写避免了两重判断最优解,会有两个max,这样只有一个max,其实,好好想一想,我前面先初始化为不选,毫无影响的,后面大于体积那我就走if,不大那就不选呗,那不还是初始化为不选。
最后那一段就是查找最优路径了。首先我先初始为背包容量,面对第i个物品时,若背包剩余容量大于体积并且从上一个状态转移过来,选了第i个物品,那它一定是最优解,并且是字典序是最小的,因为我是正序遍历的。
代码实现:
#include<iostream>
using namespace std;
int N,V;
int v[1005],w[1005],f[1005][1005];//f[i][j]表示从第i个物品开始到最后一个物品背包容量为j所获得的最大价值
int main(){cin>>N>>V;for(int i=1;i<=N;i++){cin>>v[i]>>w[i];}for(int i=N;i>=1;i--){//逆序取物,因为f[i][j]定义从i到最后for(int j=0;j<=V;j++){f[i][j]=f[i+1][j];//先初始化为不选第i个物品if(j>=v[i]){//如果背包剩余容量大于物品体积f[i][j]=max(f[i][j],f[i+1][j-v[i]]+w[i]);//那就寻找最优解,到底是选还是不选所获得总价值更大}}}int j=V;for(int i=1;i<=N;i++){if(j>=v[i]&&f[i][j]==f[i+1][j-v[i]]+w[i]){//如果f[i][j]从f[i+1][j-v[i]]+w[i]转移过来,那路径就一定是最优路径cout<<i<<" ";j-=v[i];//选了就减去背包容量,方便下次寻找}}return 0;
}
2. 多重背包问题
多重背包问题是指每种物品可以取有限次。给定一组物品,每种物品都有自己的重量、价值和一个数量限制,在不超过背包容量的前提下,选择物品的组合使得总价值最大。
算法思路:
多重背包跟01背包解法没有太大的区别,无非就是多重背包需要先进行二进制拆分,把它拆分成01背包再利用01背包求具体方案的模板进行求解。
3. 完全背包问题
完全背包问题是指每种物品可以无限取用,可以理解为无限使用。给定一组物品,每种物品都有一个重量和价值,在不超过背包容量的前提下,选择物品的组合使得总价值最大。
算法思路:
完全背包求具体方案可能就让你写第几种物品选择了几种,例如,第一种物品选择了2个,第二种物品选择了0个...这样无非又是动态规划问题。可以看一下下面思路。
-
定义状态:
- 定义
dp[w]
为当背包容量为w
时能够取得的最大价值。 - 使用
count[i][w]
来记录当背包容量为w
时,物品i
被选择了多少个。
- 定义
-
状态转移方程:
- 对于每个物品
i
,如果它的重量weight[i]
小于等于当前背包容量w
,则可以选择该物品。 - 状态转移公式为: dp[w]=max(dp[w],dp[w−weight[i]]+value[i])dp[w] = \max(dp[w], dp[w - weight[i]] + value[i])dp[w]=max(dp[w],dp[w−weight[i]]+value[i])
- 在此过程中,需要同时更新
count[i][w]
来记录物品的选择次数。
- 对于每个物品
-
初始化:
- 当不选择任何物品时,
dp[0] = 0
,其他状态初始化为 0。
- 当不选择任何物品时,
-
最终结果:
dp[W]
为在背包容量W
时能够取得的最大价值。- 通过
count
数组可以得出每种物品的选择次数。
代码实现:
#include <iostream>
#include <vector>
using namespace std;int knapsack(int W, const vector<int>& weight, const vector<int>& value, int n) {vector<int> dp(W + 1, 0);vector<vector<int>> count(n, vector<int>(W + 1, 0));// 动态规划求解完全背包问题for (int i = 0; i < n; ++i) { // 对每个物品进行处理for (int w = weight[i]; w <= W; ++w) { // 每个物品可以被多次选择if (dp[w] < dp[w - weight[i]] + value[i]) {dp[w] = dp[w - weight[i]] + value[i];count[i][w] = count[i][w - weight[i]] + 1; // 记录物品i的选择次数}}}// 输出结果cout << "最大价值: " << dp[W] << endl;cout << "每个物品的选择数量: " << endl;for (int i = 0; i < n; ++i) {cout << "物品 " << i + 1 << ": " << count[i][W] << " 个" << endl;}return dp[W];
}int main() {int W = 10; // 背包容量vector<int> weight = {2, 3, 4}; // 各个物品的重量vector<int> value = {3, 4, 5}; // 各个物品的价值int n = weight.size();knapsack(W, weight, value, n);return 0;
}
上一篇博客:背包九讲——背包问题求方案数-CSDN博客
到现在为止,背包九讲问题都更新完了,但是学习不可停止哦,以后我会分享其他的算法,或者再去更新一些知识点和例题,欢迎大家关注。笔者水平有限,一些地方做的不足的地方和需改善的地方大家可以提出来,大家有不明白的地方随时可以私信我,互相学习,大家一起加油!
执笔至此,感触彼多,全文将至,落笔为终,感谢大家支持。
相关文章:

背包九讲——背包问题求具体方案
目录 背包问题求具体方案 1. 01 背包问题 题目:12. 背包问题求具体方案 - AcWing题库 算法思路: 代码实现: 2. 多重背包问题 算法思路: 3. 完全背包问题 算法思路: 代码实现: 背包问题第九讲—…...

Python http打印(http打印body)flask demo(http调试demo、http demo、http printer)
文章目录 代码解释 代码 # flask_http_printer.pyfrom flask import Flask, request, jsonify import jsonapp Flask(__name__)app.route(/printinfo, methods[POST]) def print_info():# 分隔符separator "-" * 60# 获取请求头headers request.headers# 获取 JS…...
JSF HTML标签教程一口气讲完!(下)
JSF OutputScript示例 JSF教程 - JSF OutputScript示例 h:outputScript标记渲染类型为“script"的HTML元素,类型为“text/javascript"。 此标记将外部JavaScript文件添加到JSF页面。 以下JSF标记 <h:outputScript library"js" name"…...
cmake报错The link interface of target “gRPC::grpc“ contains: OpenSSL::SSL 解决
系统环境:麒麟V10 报错描述: The link interface of target "gRPC::grpc" contains: OpenSSL::SSL but the target was not found. Possible reasons include: * There is a typo in the target name. * A find_package call is missing fo…...

C语言PythonBash:空白(空格、水平制表符、换行符)与转义字符
C语言 空白 C语言中的空白(空格、水平制表符、换行符)被用于分隔Token,因此Token间可以有任意多个空白。 // 例1 printf("Hello, World!"); 例1中存在5个Token,分别是: printf("Hello, World! \n&qu…...
【Python】轻松解析JSON与XML:Python标准库的json与xml模块
轻松解析JSON与XML:Python标准库的json与xml模块 在现代数据处理与交换中,JSON(JavaScript Object Notation)和XML(eXtensible Markup Language)是最常用的两种数据格式。它们广泛应用于API数据传输、配置…...

物联网对商业领域的影响
互联网彻底改变了通信方式,并跨越了因地理障碍造成的人与人之间的鸿沟。然而,物联网(IoT)的引入通过使设备能够连接到互联网,改变了设备的功能。想象一下,你的闹钟连接到互联网,并且能够用你的声…...

第16章 SELECT 底层执行原理
一、SELECT查询的完整结构 1.1 方式一(SQL 92语法) SELECT ..., ..., ... FROM ..., ..., ... WHERE 多表的连接条件 AND 不包含组函数的过滤条件 GROUP BY ..., ... HAVING 包含组函数的过滤条件 ORDER BY ... ASC/DESC LIMIT ..., ... 1.2 方式二&a…...
python查询日志,并组装sql,修复缺失的数据
前言 由于mysql链接超时波动,导致数据缺失,需要根据日志填补数据 流程 获取确实数据的订单列表 搜索日志,获取请求日志 根据请求日志拼装sql 打印sql供修复数据 代码 因为我们日志打印的有问题,所以这里用字符串截取获取入…...

RecyclerView进阶知识讲解
在 Android 开发中,RecyclerView 是一种高效的列表和网格布局控件,用于显示大规模数据。尽管基本使用方法简单,但深入理解并掌握其高级进阶用法能大幅提升用户体验和应用性能。下面,我将从布局管理、动画和手势、自定义缓存、优化…...

C语言 函数
时间:2024.11.10-11.11 一、学习内容 1、什么是函数 函数:程序中独立的功能。将反复书写的代码,又不确定什么时候回用到的代码打包起来。 2、函数的基本格式 函数的定义格式(写在main函数外) void 函数名() { 函数…...

windows中docker安装redis和redisinsight记录
创建一个Redis运行容器,命令如下 docker run -it -d --name redis -p 6379:6379 redis --bind 0.0.0.0 --protected-mode no -d 代表Redis容器后台运行 --name redis 给创建好的容器起名叫redis -p 6379:6379 将容器的6379端口映射到宿主机的6379端口,注…...

itextpdf打印A5的问题
使用A5打印的时候,再生成pdf是没有问题的。下面做了一个测试,在打印机中,使用A5的纸张横向放入,因为是家用打印机,A5与A4是同一个口,因此只能这么放。 使用itextpdf生成pdf,在浏览器中预览pdf是…...

qt QUndoView详解
1、概述 QUndoView 是 Qt 框架中用于显示 QUndoStack(撤销堆栈)内容的视图类。它通常与 QUndoStack 一起使用,为用户提供了一个可视化的界面来查看和操作撤销/重做历史。QUndoView 可以显示堆栈中的每个命令,并允许用户通过界面进…...
python+智谱AI-实现钉钉消息自动回复
python智谱AI-实现钉钉消息自动回复 实现了电脑窗口切换,截图识别未读消息,与语言模型交互后,将答案带入到钉钉窗口中。偷个懒,直接贴代码了,后续不断完善注释,如果遇到读不懂的地方,欢迎交流。…...

Kafka-Eagle的配置——kafka可视化界面
通过百度网盘分享的文件:kafka-eagle-bin-2.0.8.tar.gz 链接:https://pan.baidu.com/s/1H3YONkL97uXbLTPMZHrfdg?pwdsltu 提取码:sltu 一、界面展示 二、软件配置 1、关闭kafka集群 kf.sh stop 2、将该软件上传到/opt/modules下 cd /opt…...

【命令操作】Linux上带宽流量监控nethogs命令详解 _ 统信 _ 麒麟 _ 方德
原文链接:【命令操作】Linux上带宽流量监控nethogs命令详解 | 统信 | 麒麟 | 方德 Hello,大家好啊!今天带来一篇关于Linux上nethogs命令详解的文章。nethogs是一款非常实用的网络流量监控工具,帮助用户实时查看系统中每个进程的网…...

【入门篇】数字统计——多语言版
题目跳转:数字统计 题目解析: 这道题目要求统计在给定范围 [L, R] 内所有整数中数字 2 出现的次数。例如,在范围 [2, 22] 中,数字 2 分别在数 2、12、20、21、22 中出现的次数,最终出现了6次。 题目的输入为两个正…...
探索那些现代C++语法糖
本文来聊聊现代C的一些语法糖。 1.Auto auto x 10; // 推导为 int auto y 3.14; // 推导为 double2.范围-based for 循环 std::vector<int> v {1, 2, 3, 4, 5}; for (auto val : v) {std::cout << val << " "; }3.nullptr int* ptr nullpt…...
【LeetCode】【算法】33. 搜索旋转排序数组
LeetCode 33. 搜索旋转排序数组 题目描述 整数数组 nums 按升序排列,数组中的值 互不相同 。 在传递给函数之前,nums 在预先未知的某个下标 k(0 < k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k…...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...
OkHttp 中实现断点续传 demo
在 OkHttp 中实现断点续传主要通过以下步骤完成,核心是利用 HTTP 协议的 Range 请求头指定下载范围: 实现原理 Range 请求头:向服务器请求文件的特定字节范围(如 Range: bytes1024-) 本地文件记录:保存已…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...
#Uniapp篇:chrome调试unapp适配
chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器:Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...
QT3D学习笔记——圆台、圆锥
类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体(对象或容器)QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质(定义颜色、反光等)QFirstPersonC…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...

图解JavaScript原型:原型链及其分析 | JavaScript图解
忽略该图的细节(如内存地址值没有用二进制) 以下是对该图进一步的理解和总结 1. JS 对象概念的辨析 对象是什么:保存在堆中一块区域,同时在栈中有一块区域保存其在堆中的地址(也就是我们通常说的该变量指向谁&…...
二维FDTD算法仿真
二维FDTD算法仿真,并带完全匹配层,输入波形为高斯波、平面波 FDTD_二维/FDTD.zip , 6075 FDTD_二维/FDTD_31.m , 1029 FDTD_二维/FDTD_32.m , 2806 FDTD_二维/FDTD_33.m , 3782 FDTD_二维/FDTD_34.m , 4182 FDTD_二维/FDTD_35.m , 4793...