动态规划&背包九讲&完全背包

完全背包

  • 题目:
    有N件物品和一个容量为V的背包,每种物品都有无限件可用。放入第i件物品耗费的费用为Ci,得到的价值为Wi。求解:将哪些物品装入背包,可使这些物品的耗费的费用总和不超过背包容量,且价值总和最大

  • 分析:
    这个问题类似于01背包,不同的是每件物品都有无限件,可以取0,1,2···v/ci件。

  • 状态转移方程1:
    设F[i][v]表示容量为v的背包在选择前i件物品所能获得的最大价值。

    F[i][v]=max{F[i-1][v-k*ci]+k*wi | 0<=k*ci<=v}

    此方程由01背包的状态转移方程得来(01背包具体看 01背包)。

    • 解释:每件物品都可以选择若干件,k为选择的件数。把第i件物品拆分成v/ci件物品,每件物品都是关于选或者不选的01问题,这就转化成了01背包问题了。但是此问题还有另一个状态转移方程。

  • 状态转移方程2

    F[i][v]=max{F[i-1][v],F[i][v-ci]+wi}


    • 解释:此方程与01背包方程十分相似,可能还不容易看出不同。只有F[i][v-ci]做出了改变。这样和01背包的状态方程有什么不一样的地方呢?
      01背包中每件物品只能选择0次或1次,在选择第i件物品的时候,依赖的子问题绝无选入第i件的可能,因此只能在F[i-1][]中选。
      而完全背包问题则不同,每件物品都有无限件。当背包的容量为v,取第i件物品时。要么不取,结果就跟F[i-1][v]一致;要么在可能已经选入第i种物品的结果F[i-1][v-ci]中加选一件。

  • 填表

    • 如前一篇介绍01背包的文章中说到,动态规划的问题使用填表法来理解会
    • 假设输入:
      这里写图片描述

    • F[][]表(背包容量为8)
      这里写图片描述

  • 伪代码

  • 为了别的背包问题能方便调用此函数,一般把for i to N这一层循环去掉(即在函数外循环):
    ZeroOnePack(F,C,W)
        for v<-0 to V
            F[i][v] = max{F[i-1][v],F[i][v-ci]+wi}

    //然后再
         for i<--0 to N
             ZeroOnePack(F,ci,wi)       




1. 初始化细节问题:
求最优解的问题中,事实上有两种不太相同的问法。有的题目要求恰好装满背包时的最优解,有的题目则没有要求装满。一种区别这两种问法的实现方法是初始化时有所不同。

  1. 要求恰好装满背包:F[0]设为0,其余设为负无穷。可以这样理解:放入第0件物品,只有容量为0的背包在什么也不装且价值为0的情况下恰好被装满。其他容量的背包在不装入物品的时候均没有合法的解,即不能使背包装满,属于未定义的状态,应赋予负无穷。
  2. 没有要求恰好装满背包:如果背包并非必须被装满,那么任何容量都有一个合法的解:什么也不装。所以初始状态F[0…V]均可以被赋值为0。

猜你喜欢

转载自blog.csdn.net/l_apple8/article/details/53149569