0-1背包问题简化
有N件物品和⼀个最多能被重量为W的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品只能⽤⼀次,求解将哪些物品装⼊背包⾥物品价值总和最⼤。
示例
假设背包的最大承重为max_weight,现有三个物品,分别是物品0,物品1,物品2,他们的重量分别是1,3,4,他们的价值分别是155,20,30。每件物品只能用一次,求解将哪些物品放入背包中物品的价值最大。
问题分析
物品 | 价值 | 重量 |
---|---|---|
物品0 | 15 | 1 |
物品1 | 20 | 3 |
物品2 | 30 | 4 |
##### 初始化参数
#### 物品数量
count = 3
#### 背包最大 4
max_weight = 4
#### 价值
value = [15,20,30]
#### 重量
weight = [1,3,4]
1. 确定dp数组维度。
2. 初始化dp数组。
在step1中,确定dp数组,首先我们要明确dp数组中i,j的含义,dp[i][j]代表从前i中物品里任意选择,放进容量为j的背包里的最大价值。
因此dp数组的维度应该是3×5的二维数组。
####构建dp数组
dp = [[0 for i in range(max_weight+1)] for j in range(count)]
在step2中,要初始化dp数组,在初始化dp时,对于上图可以发现,当j=0时,所有物品都不能放入,因此总价值为0,但是当j依次为1,2,3,4时,最大价值又不为零,因此在这个时候,物品0的重量小于j,因此最大价值是物品0的价值。
物品/背包容量 | 0 | 1 | 2 | 3 | 4 |
---|---|---|---|---|---|
0 | 0 | 15 | 15 | 15 | 15 |
1 | 0 | ||||
2 | 0 |
初始化dp数组的第一列与第一行
####初始化dp数组的第一列与第一行
for i in range(1):
for j in range(max_weight+1):
if weight[i] <= j:
dp[i][j] = value[i]
3.确定递推公式
dp[i][j] = dp[i-1][j]
dp[i][j] = dp[i-1][j-weight[i]]+value[i]
由dp[i - 1][j]推出,即背包容量为j,⾥⾯不放物品i的最⼤价值,此时dp[i][j]就是dp[i - 1][j]
由dp[i-1][j-weight[i]]推出,dp[i-1][j-weight[i]]为背包容量为j-weight[i]的时候不放物品i的最⼤价值,那么dp[i - 1][j - weight[i]] + value[i] (物品i的价值),就是背包放物品i得到的最⼤价值
因此 dp[i][j] = max(dp[i-1][j-weight[i]]+value[i],dp[i-1][j])
4. 判断条件 weight[i] 与 j 之间的大小
物品/背包容量 | 0 | 1 | 2 | 3 | 4 |
---|---|---|---|---|---|
0 | 0 | 15 | 15 | 15 | 15 |
1 | 0 | 15 | 15 | 20 | 35 |
2 | 0 | 15 | 15 | 20 | 35 |
for i in range(1,count):
for j in range(1,max_weight+1):
if j >= weight[i]:
dp[i][j] = max(dp[i-1][j-weight[i]]+value[i],dp[i-1][j])
else:
dp[i][j] = dp[i-1][j]
在这里从i=1,j=1开始遍历的原因是第一行,第一列我们已经初始化过。
全部代码
##### 初始化参数
#### 物品数量
count = 3
#### 背包最大 4
max_weight = 4
#### 价值
value = [15,20,30]
#### 重量
weight = [1,3,4]
####构建dp数组
dp = [[0 for i in range(max_weight+1)] for j in range(count)]
####初始化dp数组的第一列与第一行
for i in range(1):
for j in range(max_weight+1):
if weight[i] <= j:
dp[i][j] = value[i]
#### 递归
for i in range(1,count):
for j in range(1,max_weight+1):
if j >= weight[i]:
dp[i][j] = max(dp[i-1][j-weight[i]]+value[i],dp[i-1][j])
else:
dp[i][j] = dp[i-1][j]
#### 输出最后结果
print(max(max(dp)))