【二】01背包

这段代码实现了一个动态规划算法,用于解决给定容量的背包能装入物品的最大价值问题。输入包括物品的重量w和价值v,以及背包的容量c。程序通过二维数组dp动态存储每个状态下的最大价值,最后输出在不超过背包容量的情况下,能获得的最大价值。
#include<iostream>
using namespace std;
int n,c;
int w[15];
int v[15];
int dp[15][1000];

void solve()
{
    for(int j=0;j<=c;j++)
        dp[0][j]=0;
    for(int i=0;i<=n;i++)
        dp[i][0]=0;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=c;j++)
        {
            if(w[i]>j)
                dp[i][j]=dp[i-1][j];
            else
                dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]);
        }
}

int main()
{
    while(cin>>n>>c&&(n||c))
    {
        for(int i=1;i<=n;i++)
            cin>>w[i];
        for(int i=1;i<=n;i++)
            cin>>v[i];
        solve();
        cout<<dp[n][c]<<endl;
    }
    return 0;
}

 

 

### 01背包问题简介 01背包问题是经典的一维01背包问题的扩展,其核心在于考虑两个维度的约束条件。例如,在传统的01背包问题中,只关注物品的重量和价值之间的权衡关系;而在01背包问题中,则需要同时满足两种资源的限制条件(如体积和重量)。这种问题通常可以通过动态规划方法高效解决。 --- ### 动态规划算法思路 设 `dp[i][j][k]` 表示从前 `i` 个物品中选取若干个放入容量为 `(j, k)` 的背包所能获得的最大价值。状态转移方程如下: - 如果不选第 `i` 个物品: \[ dp[i][j][k] = dp[i-1][j][k] \] - 如果选择第 `i` 个物品(前提是该物品的两维消耗不超过当前剩余空间): \[ dp[i][j][k] = max(dp[i-1][j-v_i][k-w_i] + val_i, dp[i-1][j][k]) \] 其中: - \(v_i\) 是第 `i` 个物品的第一维消耗; - \(w_i\) 是第 `i` 个物品的第维消耗; - \(val_i\) 是第 `i` 个物品的价值。 最终的结果存储在 `dp[N][C_1][C_2]` 中,表示前 `N` 个物品在两维分别为 `C_1` 和 `C_2` 的背包中的最大价值[^1]。 为了降低时间复杂度和空间复杂度,可以采用滚动数组的方式优化三维 DP 到维 DP。 --- ### Python 实现代码 以下是基于动态规划01背包问题的具体实现代码: ```python def two_dimensional_knapsack(n, capacity_v, capacity_w, v_list, w_list, value_list): """ 参数说明: n: 物品数量 capacity_v: 背包第一维容量 capacity_w: 背包维容量 v_list: 各物品第一维消耗列表 w_list: 各物品第维消耗列表 value_list: 各物品对应价值列表 返回值:最大总价值 """ # 创建维DP表,默认初始化为0 dp = [[0] * (capacity_w + 1) for _ in range(capacity_v + 1)] # 遍历每个物品 for i in range(1, n + 1): vi, wi, val = v_list[i - 1], w_list[i - 1], value_list[i - 1] for j in range(capacity_v, vi - 1, -1): # 倒序遍历第一维 for k in range(capacity_w, wi - 1, -1): # 倒序遍历第维 dp[j][k] = max(dp[j][k], dp[j - vi][k - wi] + val) return dp[capacity_v][capacity_w] # 测试数据 if __name__ == "__main__": N = 3 # 物品数 C_V = 25 # 第一维容量 C_W = 25 # 第维容量 V_LIST = [20, 15, 10] # 各物品第一维消耗 W_LIST = [10, 15, 20] # 各物品第维消耗 VALUE_LIST = [20, 30, 25] # 各物品价值 result = two_dimensional_knapsack(N, C_V, C_W, V_LIST, W_LIST, VALUE_LIST) print(f"最大总价值为: {result}") ``` --- ### Java 实现代码 如果更倾向于使用 Java 编写,以下是一个等效的实现方式: ```java import java.util.Scanner; public class TwoDimensionalKnapsack { public static int solve(int n, int capV, int capW, int[] vList, int[] wList, int[] valueList) { int[][] dp = new int[capV + 1][capW + 1]; for (int i = 1; i <= n; i++) { int vi = vList[i - 1]; int wi = wList[i - 1]; int val = valueList[i - 1]; for (int j = capV; j >= vi; j--) { for (int k = capW; k >= wi; k--) { dp[j][k] = Math.max(dp[j][k], dp[j - vi][k - wi] + val); } } } return dp[capV][capW]; } public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int capV = sc.nextInt(); int capW = sc.nextInt(); int[] vList = new int[n]; int[] wList = new int[n]; int[] valueList = new int[n]; for (int i = 0; i < n; i++) { vList[i] = sc.nextInt(); wList[i] = sc.nextInt(); valueList[i] = sc.nextInt(); } int result = solve(n, capV, capW, vList, wList, valueList); System.out.println(result); sc.close(); } } ``` --- ### 性能分析 上述算法的时间复杂度为 \(O(N \cdot C_1 \cdot C_2)\),其中 \(N\) 是物品的数量,\(C_1\) 和 \(C_2\) 分别是两个维度的容量上限。通过倒序更新策略避免了额外的空间开销,因此空间复杂度降为 \(O(C_1 \cdot C_2)\)[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值