📅  最后修改于: 2023-12-03 14:54:32.626000             🧑  作者: Mango
扩展背包问题是一个经典的动态规划问题,它可以描述在给定背包容量下,如何选择不同的物品进行装载以达到最大的总价值或总利润。
有一个背包,它的容量为 C
。现有 N
种物品,每种物品有一个重量 w
和一个价值 v
。要求选择一些物品放入背包中,使得背包中物品的总重量不超过容量 C
,且物品的总价值最大。
0/1 背包问题是扩展背包问题的一种特殊情况,即每种物品只有一个或零个可供选择。可以使用动态规划的方法求解该问题。
定义一个二维数组 dp
,其中 dp[i][j]
表示在前 i
个物品中选择,且背包容量为 j
时的最大总价值。
对于每个物品,有两个选择:装入背包或不装入背包。
dp[i-1][j-w] + v
,其中 w
是当前物品的重量,v
是当前物品的价值。dp[i-1][j]
。
最终的状态转移方程为 dp[i][j] = max(dp[i-1][j-w] + v, dp[i-1][j])
。i=0
时,表示前0个物品,此时最大总价值为0,即 dp[0][j] = 0
。j=0
时,表示背包容量为0,此时最大总价值为0,即 dp[i][0] = 0
。def knapsack_01(capacity, weights, values):
n = len(weights)
dp = [[0] * (capacity + 1) for _ in range(n + 1)]
for i in range(1, n + 1):
for j in range(1, capacity + 1):
if j >= weights[i-1]:
dp[i][j] = max(dp[i-1][j-weights[i-1]] + values[i-1], dp[i-1][j])
else:
dp[i][j] = dp[i-1][j]
return dp[n][capacity]
完全背包问题是扩展背包问题的另一种特殊情况,即每种物品可以选择任意个。同样可以使用动态规划的方法求解该问题。
定义一个二维数组 dp
,其中 dp[i][j]
表示在前 i
个物品中选择,且背包容量为 j
时的最大总价值。
对于每个物品,有多个选择:装入0个、1个、2个,直到 k
个物品,其中 k
满足 k*w <= j
。
k
个物品,那么最大总价值为 dp[i-1][j-k*w] + k*v
。
最终的状态转移方程为 dp[i][j] = max(dp[i-1][j-k*w] + k*v) (0 <= k*w <= j)
。i=0
时,表示前0个物品,此时最大总价值为0,即 dp[0][j] = 0
。j=0
时,表示背包容量为0,此时最大总价值为0,即 dp[i][0] = 0
。def knapsack_complete(capacity, weights, values):
n = len(weights)
dp = [[0] * (capacity + 1) for _ in range(n + 1)]
for i in range(1, n + 1):
for j in range(1, capacity + 1):
k = j // weights[i-1]
dp[i][j] = dp[i-1][j]
for m in range(k+1):
dp[i][j] = max(dp[i][j], dp[i-1][j-m*weights[i-1]] + m*values[i-1])
return dp[n][capacity]
扩展背包问题是一个经典的动态规划问题,它可以使用两种方法求解:0/1 背包问题和完全背包问题。通过状态定义、状态转移方程和初始化条件,程序员可以轻松解决背包问题,并获得最优解。