当前位置:网站首页>「动态规划」0/1背包问题
「动态规划」0/1背包问题
2022-06-10 07:02:00 【安和橋北】
问题描述
给定n种物品和一个背包,物品i的重量是wi,其价值为 v i,背包的容量为C。
背包问题是如何选择装入背包的物品,使得装入背包中物品的总价值最大? 如果在选择 装入背包的物品时,对每种物品i只有两种选择:装入背包或不装入背包,即不能将物品i装入背包多次,也不能只装入物品i的一部分,则称为0/1背包问题
思路分析
1. 确定状态转移
在0/1背包问题中首先需要考虑的限制条件就是:如果当前的第 i 个物品的重量大于了背包的剩余容量,那么就不能装入。
如果能装入,那我们再考虑到底要不要装入?也就是从 “装入” 和 “不装入”两个方面来获得背包的最大价值。
因此定义dp数组:dp [ i ] [ j ]
表示当背包的容量为 j 的时候,装入前 i 个物品可以获得的最大价值。
上述对 i 的解释是错误的,如果能装入前 i 个,那么总价值已经确定了,就没必要算了。
所以正确的解释是:
表示当背包的容量为 j 的时候,对于前 i 个物品,可以获得的最大价值。也就是可装可不装。
2. 求出装入背包的具体物品
即获得我们本次算出的最优解,不仅是得出结果。
我们用一个一维数组 isLoad[ i ] 来表示物品 i 有没有被装入。值为1表示装入,为0表示未装入。
为了确定装入背包的具体物品,我们从 dp[ n ] [ w ] 往前推。如果dp[ n ] [ w ] > dp [ n - 1] [ w ],则说明第n个物品肯定被装入了背包,因为此时背包的价值更大。否则物品n肯定没有被放入背包。一个if-else就可以解决问题。
注意点
在下面代码中,weight和value数组的下标是从1开始的,对应第 i 个物品。0下标没有用,数值用0代替。
代码
#include <iostream>
#include <math.h>
using namespace std;
int knapSack(int n, int w, int weight[], int value[], int isLoad[]) {
// 多开辟的一个空间是为了容量为0和不装东西的情况
int dp[n+1][w+1]; // 定义dp数组 表示当容量为w的时候,对于前i个物品可以获得的最大价值
for(int i = 0 ; i <= n; i++) dp[i][0] = 0; // 容量为0
for(int i = 0 ; i <= w ; i++) dp[0][i] = 0; // 不装东西
// 动态规划
for(int i = 1 ; i <= n; i++) {
for(int j = 1 ; j <= w ; j++) {
// 准备放第i个物品
if(j < weight[i]) {
// 背包的剩余容量不够了 就不放
dp[i][j] = dp[i-1][j]; // 不装
} else {
dp[i][j] = max(dp[i-1][j], dp[i-1][j-weight[i]] + value[i]);
}
}
}
// 获得装入背包的物品 存放在isLoad数组中
int j = w;
for(int i = n ; i >= 1 ; i--) {
// 第i个物品
if(dp[i][j] > dp[i-1][j]) {
isLoad[i] = 1;
j -= weight[i];
}
else {
isLoad[i] = 0;
}
}
return dp[n][w];
}
int main() {
int n = 3;
int w = 4;
int weight[4] = {
0,2,1,3};
int value[4] = {
0,4,2,3}; // 下标从1开始 0下标不用 直接设置为0
int isLoad[4];
int maxValue = knapSack(n,w,weight,value,isLoad);
cout<<"最大价值是"<<maxValue;
for(int i = 1; i <=n ; i++) cout<<isLoad[i]<< " ";
}
边栏推荐
- Why can't lldb print view bounds? - Why can't LLDB print view. bounds?
- Unlock TRPC high performance password: introduction to network scheme!
- R语言怎么利用ggplot2绘制QQ图和箱线图
- Tensorflow experiment 10 - image flipping and zooming
- 成功解决:ImportError: cannot import name ‘Imputer‘ from ‘sklearn.preprocessing
- findfont: Font family [‘msyh‘] not found. Falling back to DejaVu Sans.
- 一举刷新 54 个中文 NLP 任务基准,ERNIE3.0加持下的EasyDL可能是市面上最好用的NLP开发平台...
- 用友OA漏洞复现手册
- Local storage of JS data interaction
- loj10131. 「一本通 4.4 例 2」暗的连锁 题解 树上差分(边差分)
猜你喜欢

Qt--- create dialog box 3: implementation of shape variable dialog box
![[dynamic programming] Game Theory: a collection of stone games](/img/ae/98e0fe741ed6c90e83cba244392c88.png)
[dynamic programming] Game Theory: a collection of stone games

Unlock TRPC high performance password: introduction to network scheme!

Embedded development | common operations of EEPROM driver code

小程序:通过getCurrentPages获取当前页面路由信息

YoseZang 原创 特征码定位器 SignatureTest V6.36 Rls 发布

How to quickly clip multiple short videos and remove Video Trailer

POC_ Jenkins

Deploy MySQL based on statefulset in kubernetes (Part 1)

【计量经济学】工具变量估计与两阶段最小二乘法
随机推荐
Solving the problem of interval updating + interval maximum value by block sequence
Chenxi bookkeeping book for bookkeeping, and use items to view accounts
Opencv learning (II) -- installing opencv on raspberry pie
电容隔离原理
27. encapsulate an animation function
键盘事件与表单事件
数列分块解决区间更新+区间最值问题
Unity fully elastic collision
How to solve mysql1045 and find the prompt is not an internal command
LabVIEW控制Arduino实现红外测距(进阶篇—6)
Baidu cloud address identification
Cesium 1.91 update log - MSAA and native promise are coming
Teleyecontroller v8.69 reconfiguration of keyboard recording function release by:yose
用友OA漏洞复现手册
Problem: interceptor missile
Teleyecontroller v8.47 release changes socket framework
原博客的地址
Typecho template vcards/ simple and personalized personal blog theme template
Abnormal display of mobile signal at startup
TeleyeControlor V8.47版本发布 更改Socket框架