• 基本算法0/1背包问题


      关于0/1背包问题网上有非常多的博文,在此我谨记录一下自己的理解。

      问题表述:有N件物品和一个容量为V的背包。第i件物品的体积是C[i](0<=i<=N-1),价值是W[i]。求解将哪些物品装入背包可使价值总和最大。每个物品最多只可以放入背包一次。

      这个问题的经典解法思路如下:

      我们用f[i][j]表示在考虑前i个物品时体积为j的背包的最大价值,注意,我们并不是把前i个物品全部放入背包,而是考虑i个物品中挑选一些放入背包,使得价值最大的那些情况。

      首先,我们考虑只有1个物品(第0个)时,容量分别为0,1,...,V的各背包所包含物品的最大价值。很明显,容量大于等于C[0]的背包的最大价值为W[0],容量小于C[0]的背包的最大价值为0。

      然后,我们考虑再来一个(第i个)物品时,容量分别为0,1,...,V的各背包所包含物品的最大价值。对于某个背包,我们有两种选择:将该物品放入该背包或者不放入。

      当我们将该物品放入某个体积为j的背包时,该背包的最大价值为f[i][j-C[i]]+W[i]。当我们不把该物品放入某个体积为j的背包时,该背包的最大价值为f[i-1][j]。所以在考虑前i个物品时,体积为j的背包的最大价值为f[i][j]=max{f[i-1][j],f[i][j-C[i]]+W[i]}.

      迭代以上步骤,从i=0到N-1,最后得到的f[N-1][V]就是最后的答案。

      上述算法的时间复杂度为O(VN),空间复杂度也是O(VN)。时间复杂度是最优的,而空间复杂度可以进一步优化:我们注意到在公式f[i][j]=max{f[i-1][j],f[i][j-C[i]]+W[i]}中,对于j从0到V,f[i][j]只与f[i-1][j]有关,而与i-2,i-3等情况下的f无关,所以我们只需要考虑前一次迭代(亦即i-1)的结果就可以。亦即f[j]=max{f[j],f[j-C[i]]+W[i]}.又因为在计算f[j]时用到了比j小的f:f[j-C[i]],所以在对j进行迭代时应该从后向前迭代: 

    1   for(int i=0;i<N;i++){
    2             for(int j=V;j>=0;j--){
    3                 if(j-item[i][0]>=0){//此处判断是为了防止将j物品放入容量小于C[j]的背包中
    4                     f[j]=max(f[j],f[j-item[i][0]]+item[i][1]);
    5                 }
    6             }           
    7         }

      我们可以用一个例子来展示一下上述代码迭代的过程。取V=10,N=3.三个物品的体积分别为3,4,5.价值分别为4,5,6,迭代过程中f数组的值为:

      0 0 0 4 4 4 4 4 4 4 4
      0 0 0 4 5 5 5 9 9 9 9
      0 0 0 4 5 6 6 9 10 11 11

      第一行为只考虑第1个物品的情况。所有容量大于等于3的背包的价值都为该物品的价值:4.

      第二行为只考虑前2个物品的情况。所有容量大于等于7的背包可以同时容纳前2个物品,价值为4+5=9,容量为4-6的背包可以容纳第2个物品,价值为5,容量为3的背包可以容纳第1个物品,价值为4.

      第三行以此类推。

      我们取最后1行的最后一个数字为结果,亦即考虑所有3个物品的体积为10的背包的最大价值,为11.

    参考文献:

      [1] 0/1问题 动态规划法

      [2] 背包问题九讲 第一讲 0/1背包问题

      [3] 背包之0/1背包 完全背包 多重背包详解

     

  • 相关阅读:
    用Tinkercad学arduino之 LCD电压电流表
    用Tinkercad学arduino之 L293D电机驱动器驱动直流电机
    用Tinkercad学arduino之 74HC595 寄存器控制1位7段数码管
    用Tinkercad学arduino之 74HC595寄存器控制8个led跑马灯
    用Tinkercad学arduino之 红外遥控器
    用Tinkercad学arduino之 人体红外检测报警 LCD显示
    用Tinkercad学arduino之 人体红外检测报警 蜂鸣器+LED
    用Tinkercad学arduino之 电位器控制伺服电机转向
    用Tinkercad学arduino之 光线控制彩灯
    用Tinkercad学arduino之 温度LED报警
  • 原文地址:https://www.cnblogs.com/kemaswill/p/2711665.html
Copyright © 2020-2023  润新知