0/1背包问题
问题描述:一个容量大小为n的背包,每件物品的重量为
w
e
i
g
h
t
[
i
]
weight[i]
weight[i],每件物品对应的价值
v
a
l
u
e
[
i
]
value[i]
value[i],物品不可分割,找到背包中物品价值总和的最大值。
如下图所示:假设背包容量为7,使得背包价值最大的组合是物品1+物品2=55

求解算法:动态规划
求解思路:
(1)初始化一个二维数组
d
p
[
r
o
w
]
[
c
o
l
]
dp[row][col]
dp[row][col],其中
r
o
w
=
row =
row= 物品的数量,
c
o
l
=
col =
col=背包的最大容量,
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j] 表示从下标为
[
0
−
i
]
[0-i]
[0−i]的物品里任意取,放进容量为j的背包,价值总和最大是多少。
vector<vector<int>> dp(weight.size(), vector<int> (bagCapacity + 1,0));

(2)改变第一行,当 j > = w e i g h t [ 0 ] j >= weight[0] j>=weight[0] 时,表示把物品 0 放入背包,此时背包的价值 = v a l u e [ 0 ] = value[0] =value[0]
for(int j = weight[0]; j <= bagCapacity; j++) {
dp[0][j] = value[0];
}

(3)改变其余行,当
j
<
w
e
i
g
h
t
[
i
]
j < weight[i]
j<weight[i] 时,说明背包中还没放入新的物品,此时
d
p
[
i
]
[
j
]
=
d
p
[
i
−
1
]
[
j
]
dp[i][j] = dp[i - 1][j]
dp[i][j]=dp[i−1][j];当
j
>
w
e
i
g
h
t
[
i
]
j>weight[i]
j>weight[i] 时,状态转移方程为:
d
p
[
i
]
[
j
]
=
m
a
x
(
d
p
[
i
−
1
]
[
j
]
,
d
p
[
i
−
1
]
[
j
−
w
e
i
g
h
t
[
i
]
]
+
v
a
l
u
e
[
i
]
)
;
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
dp[i][j]=max(dp[i−1][j],dp[i−1][j−weight[i]]+value[i]);
for(int i = 1; i < weight.size(); i++) {
for(int j = 0; j <= bagCapacity; j++) {
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]);
}
}
}

数组右下角的数值即为背包的最大价值。
完整c++代码:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
// 物品的重量,价值
vector<int> weight = {2,3,4,5};
vector<int> value = {10,25,30,40};
// 背包的最大容量
int bagCapacity = 7;
// row = weight.size(), col = bagCapacity + 1
// 二维数组
vector<vector<int>> dp(weight.size(), vector<int> (bagCapacity + 1,0));
// 初始化二维数组
// 矩阵的第一行,当物品0的重量大于背包容量时,dp[][]=0,反之dp[][]=value[0]
for(int j = weight[0]; j <= bagCapacity; j++) {
dp[0][j] = value[0];
}
// 遍历
for(int i = 1; i < weight.size(); i++) {
for(int j = 0; j <= bagCapacity; j++) {
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]);
}
}
}
// for(int i = 0; i < dp.size(); i++){
// for(int j = 0; j <= bagCapacity; j++) {
// cout<<dp[i][j]<<" ";
// }
// cout<<endl;
// }
cout<<dp[weight.size() - 1][bagCapacity]<<endl;
}
参考:https://programmercarl.com/
6万+

被折叠的 条评论
为什么被折叠?



