📜  扩展背包问题(1)

📅  最后修改于: 2023-12-03 14:54:32.626000             🧑  作者: Mango

扩展背包问题

简介

扩展背包问题是一个经典的动态规划问题,它可以描述在给定背包容量下,如何选择不同的物品进行装载以达到最大的总价值或总利润。

问题描述

有一个背包,它的容量为 C。现有 N 种物品,每种物品有一个重量 w 和一个价值 v。要求选择一些物品放入背包中,使得背包中物品的总重量不超过容量 C,且物品的总价值最大。

解决方案
1. 0/1 背包问题

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]
2. 完全背包问题

完全背包问题是扩展背包问题的另一种特殊情况,即每种物品可以选择任意个。同样可以使用动态规划的方法求解该问题。

状态定义

定义一个二维数组 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 背包问题和完全背包问题。通过状态定义、状态转移方程和初始化条件,程序员可以轻松解决背包问题,并获得最优解。