背包(二维数组版和一维数组版)

本文深入探讨了动态规划在解决背包问题中的应用,详细阐述了二维数组和一维数组两种表示方法。通过示例解释了dp数组的含义、递推公式以及初始化过程。强调了在从二维转为一维过程中,遍历顺序的重要性,特别是逆序遍历可以避免重复计算,确保计算正确性。同时,文章指出了不同遍历方式在处理同一物品在不同背包容量下价值时的差异。
摘要由CSDN通过智能技术生成

一:前言

这是动态规划的经典题型,那么我们也是 按照动态规划五步走的策略分析的

  • 确定dp数组的含义以及下标的含义
  • 确定dp数组的递推公式
  • 确定dp数组的初始化
  • 确定dp数组的遍历顺序
  • 举例验证(如果不是做题可省略)

二:二维数组

1:示例

在这里插入图片描述

2:dp数组的含义

**dp[i][j]**表示的是物品[0,i]放入背包容量为j的时候最大价值

3:确定dp数组的递推公式

dp[i][j] = max(dp[i-1][j], value[i] + dp[i-1][j-weight[i]])

在这里插入图片描述

4:初始化

在这里插入图片描述

5:遍历顺序


for(int i = 1; i < weight.size(); i++) {//物品数量  从1开始是因为我们的 我们  
    for(int j = 0; j <= baseweight; j++) {                        //第0件物品已经初始化号了
         if(j < weight[i]) dp[i][j] = dp[i-1][j];
         else dp[i][j] = max(dp[i-1][j], value[i] + dp[i-1][j-weight[i]])
    }
}

在这里插入图片描述

三:一维数组版

1:如何从二维数组变化到一维数组

因为我们是可以压缩二位数组的,二维数组中的dp[i-1][j] 我们可以 直接拷贝 下来为dp[i][j],
(这个意思就是我们在计算当前方格的时候 直接拿上一个放方格值拿过来,这其实就是不放物品i, 对此我们可以选择的是放入物品i后的价值+空间的价值与其进行比较)

那二维数组的递推公式: dp[i][j] = max(dp[i][j], dp[i][j - weight[i]] + value[i] );

那么基于此的话 我们可以将其转化为一维数组

即: dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
(这里的j代表的背包容量 ;
max中的两部分:dp[j]:不放物品i; dp[j - weight[i]] + value[i]:放入物品i);

2:dp数组的含义

dp[j] 代表的是背包容量为j的时候的最大价值

3:dp数组的递推公式

即: dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
(这里的j代表的背包容量;
max中的两部分:dp[j]:不放物品i; dp[j - weight[i]] + value[i]:放入物品i);

4:dp数组的初始化

将其初始化为0 因为我们需要将其中的部分为max部分

5:dp数组的遍历顺序

(1):正文

这里需要辨析正序遍历和逆序遍历

  • 正序遍历(会出现重复计算的值)
    在这里插入图片描述
  • 逆序遍历
    在这里插入图片描述
  • 说白了也就正序遍历的时候 会用到前面已经计算出来的结果 那么就会出现 重复
    那么逆序的时候,我们也是用到前面的dp,但是其还没有计算出结果初始化为0

(2):引发的问题(那为啥二维dp数组的背包重量没有逆序呢?)

一维数组:dp[j-weight[i]] + value[i]
二维数组:dp[i-1][j-weight[i]] +value[i]

  • 其实本质上就是比较放入物品i后, 剩余空间的背包容量是否会出现重复放入商品的的状况
    那么二位数组的话我们是需要先计算出上层的的表格数据(也就是前几件物品放入背包后的状况,),因为我们需要计算剩余空间的最大价值。
  • 那么我们的一维数组也是需要计算剩余空间的最大价值呀?这样逆序的话怎么计算?
    对于此的话我们要先明白这是同一件物品 在不同的j(背包容量下的价值),如果我们正序
    的话,那就相当于将同一间物品放入了不同j下的背包两次 这是 不允许的,那么逆序就会解决这一切;只要保证了我们同一件物品在不同的j下的正确结果,那么我们才能计算出正确的dp[j]供 dp[j-weight] (求剩余空间的最大价值用)

(3):上码

   vector<int>dp(n+1;//总共有n件物品
   for(int i = 0; i < weight.size(); i++) {//遍历物品
     for(int j = baseWeight; j >= weight[i];  j--) {//这里我们只遍历到weight[i]
                                                  //是因为如果背包的容量小于weight[i]
                                                  //的话那么我们是装不下的   
      dp[j] = max(dp[j],dp[j-weight[i]] + value[i])
     }
   }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天天向上的菜鸡杰!!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值