01背包问题---动态规划

本文介绍了一种使用动态规划解决0/1背包问题的方法,详细解析了动态规划的基本思想,提供了完整的C++代码实现,并分析了算法的时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

借鉴于:https://www.cnblogs.com/xym4869/p/8513801.html

 

动态规划法求解0/1背包问题:

 

1)基本思想:

令表示在前个物品中能够装入容量为的背包中的物品的最大值,则可以得到如下动态函数:

            

 

   2)代码:

复制代码

#include <iostream>
#include<cstdio>
#define N 100
#define MAX(a,b) a < b ? b : a
using namespace std;

struct goods{
int sign;//物品序号
int wight;//物品重量
int value;//物品价值
};

int n,bestValue,cv,cw,C;//物品数量,价值最大,当前价值,当前重量,背包容量
int X[N],cx[N];//最终存储状态,当前存储状态
struct goods goods[N];

int KnapSack(int n,struct goods a[],int C,int x[]){
    int V[N][10*N];
    for(int i = 0; i <= n; i++)//初始化第0列
        V[i][0] = 0;
    for(int j = 0; j <= C; j++)//初始化第0行
        V[0][j] = 0;
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= C; j++)
        if(j < a[i-1].wight)
            V[i][j] = V[i-1][j];
        else
            V[i][j] = MAX(V[i-1][j],V[i-1][j-a[i-1].wight] + a[i-1].value);

    for(int i = n,j = C; i > 0; i--){
        if(V[i][j] > V[i-1][j]){
            x[i-1] = 1;
            j = j - a[i-1].wight;
        }
        else
            x[i-1] = 0;
    }
    return V[n][C];
}
int main()
{
    printf("物品种类n:");
    scanf("%d",&n);
    printf("背包容量C:");
    scanf("%d",&C);
    for(int i = 0; i < n; i++){
        printf("物品%d的重量w[%d]及其价值v[%d]:",i+1,i+1,i+1);
        scanf("%d%d",&goods[i].wight,&goods[i].value);
    }
    int sum2 = KnapSack(n,goods,C,X);
     printf("动态规划法求解0/1背包问题:\nX=[");
     for(int i = 0; i < n; i++)
        cout<<X[i]<<" ";//输出所求X[n]矩阵
     printf("]   装入总价值%d\n", sum2);
     return 0;
}

复制代码

 

3)复杂度分析:

动态规划法求解0/1背包问题的时间复杂度为:n*C

 

### 01背包问题动态规划解法 #### 定义与背景 动态规划是一种通过将复杂问题分解为更简单子问题的方法来解决问题的技术[^1]。当面对像01背包这样的优化问题时,这种方法尤为有效。 #### 动态规划的核心概念 核心在于构建一个二维表`dp[i][j]`,其中`i`代表考虑的商品数量(即前`i`个商品),而`j`则表示可用的空间大小(即背包容量)。此表格用于存储在给定条件下可以获得的最大总价值[^5]。 #### 构建状态转移方程 对于每一个可能的状态`(i,j)`,存在两种情况: - 如果不选择第`i`项,则最大价值等于只考虑前`i-1`项且同样剩余空间`j`的情况下的最优解; - 若选择了第`i`项,则新的剩余空间变为`j-w_i`(前提是`w_i≤j`),此时最大价值应加上该项的价值`v_i`再加上仅限于前`i-1`项但在缩小后的空间内能取得的最佳结果。 最终的选择取决于哪种方案能够带来更高的收益。形式化表达如下: \[ dp[i][j]=\max(dp[i−1][j], v_i+dp[i−1][j−w_i]) \quad (if \; w_i ≤ j)\] 这里,\(w_i\) 和 \(v_i\) 分别指代第 `i` 物品的重量及其对应的价值[^4]。 #### 初始化条件 通常情况下,设置边界条件为:没有任何物品可选(`i=0`)或完全没有空间(`j=0`)的情况下,所能获取的最大价值自然都设定为零;另外还需注意初始化第一行数据——只有单件物品可供挑选时,在不超过其自身重量的前提下尽可能多地放入该物品以实现最大化价值。 #### Python代码示例 以下是基于上述理论编写的Python程序片段,用来计算并打印出针对特定输入参数集的结果: ```python def knapsack(weights, values, capacity): n = len(values) # 创建DP table 并全部设为0 dp = [[0 for _ in range(capacity + 1)] for __ in range(n + 1)] for i in range(1, n + 1): # 遍历每一件物品 for w in range(1, capacity + 1): # 对每个可能的背包容积进行迭代 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][capacity] weights = [20, 15, 10] values = [20, 30, 25] capacity = 25 print(f"The maximum value that can be put into the bag is {knapsack(weights, values, capacity)}") ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值