0/1 背包问题

0/1 背包问题是一种经典的计算机科学和数学问题,也是动态规划的典型应用。问题描述如下:

问题描述

给定一个容量为 ( W ) 的背包和 ( n ) 个物品,每个物品有一个重量 ( w_i ) 和价值 ( v_i )。每个物品只能被选择一次(即不能部分选取)。目标是选择一些物品装入背包,使得在不超过背包容量的前提下,这些物品的总价值最大。

形式化定义

  • 输入

    • ( W ):背包的最大容量。
    • ( n ):物品的数量。
    • ( w[i] ):第 ( i ) 个物品的重量。
    • ( v[i] ):第 ( i ) 个物品的价值。
  • 输出

    • 能装入背包的物品的最大总价值。

示例

假设有如下物品和背包:

  • 背包容量 ( W = 10 )
  • 物品列表:
    • 物品 1:重量 2,价值 3
    • 物品 2:重量 3,价值 4
    • 物品 3:重量 4,价值 5
    • 物品 4:重量 5,价值 8

通过选择物品 1、物品 2 和物品 4,可以达到最大价值 3 + 4 + 8 = 15,总重量为 10。

动态规划解法

为了使用动态规划解决 0/1 背包问题,我们定义一个二维数组 dp,其中 dp[i][j] 表示前 ( i ) 个物品在容量不超过 ( j ) 的情况下能够取得的最大价值。

状态转移方程

[ dp[i][j] = \max(dp[i-1][j], dp[i-1][j-w[i]] + v[i]) ]

其中:

  • dp[i-1][j] 表示不选择第 ( i ) 个物品的情况。
  • dp[i-1][j-w[i]] + v[i] 表示选择第 ( i ) 个物品的情况。
初始条件

[ dp[0][j] = 0 ]
表示没有物品可选时,所有容量的最大价值为 0。

C++ 实现

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

// 0/1 背包问题的解决方案
int knapsack(int W, const vector<int>& weights, const vector<int>& values, int n) {
    // 定义 DP 数组
    vector<vector<int>> dp(n + 1, vector<int>(W + 1, 0));

    // 填充 DP 数组
    for (int i = 1; i <= n; ++i) {
        for (int w = 1; w <= W; ++w) {
            if (weights[i - 1] <= w) {
                dp[i][w] = max(dp[i - 1][w], dp[i - 1][w - weights[i - 1]] + values[i - 1]);
            } else {
                dp[i][w] = dp[i - 1][w];
            }
        }
    }

    // 返回背包最大价值
    return dp[n][W];
}

int main() {
    int W = 10; // 背包容量
    vector<int> weights = {2, 3, 4, 5}; // 物品重量
    vector<int> values = {3, 4, 5, 8};  // 物品价值
    int n = weights.size(); // 物品数量

    cout << "Maximum value in Knapsack: " << knapsack(W, weights, values, n) << endl;

    return 0;
}

代码解释

  1. 定义 DP 数组

    • vector<vector<int>> dp(n + 1, vector<int>(W + 1, 0));:创建一个大小为 (n + 1) x (W + 1) 的二维数组,初始值全为 0。
  2. 填充 DP 数组

    • 遍历每个物品 i 和每个容量 w
    • 如果当前物品的重量 weights[i - 1] 小于等于当前容量 w,则选择 max(dp[i - 1][w], dp[i - 1][w - weights[i - 1]] + values[i - 1])
    • 否则,保持 dp[i][w] = dp[i - 1][w]
  3. 返回结果

    • dp[n][W] 表示在背包容量为 W 的情况下,能取得的最大价值。

总结

0/1 背包问题通过动态规划方法,可以在多项式时间内解决,这使得它在处理大规模数据时也具有较高的效率和准确性。该问题及其解决方案在许多优化和资源分配问题中都有广泛的应用。

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值