美文网首页动态规划动态规划
完全背包问题(动态规划法-DP含一维滚动数组优化)

完全背包问题(动态规划法-DP含一维滚动数组优化)

作者: JaJIng | 来源:发表于2019-04-03 11:45 被阅读0次

完全背包问题:
有n个重量分别为{w1,w2,…,wn}的物品,它们的价值分别为{v1,v2,…,vn},给定一个容量为W的背包。小偷要选择从这些物品中偷一部分物品放入该背包的方案,每个物品可以偷任意个,要求选中的物品不仅能够放到背包中,而且重量和为W具有最大的价值。
该题是0-1背包问题的扩展,0-1背包是某个物品偷或者不偷,完全背包是某个物品要偷多少个?
从0-1背包问题那我们推断出了一个状态转移公式:
B(i,w) = max( B(i-1,w) ,B(i-1,w-c(i))+v(i) )
其中,i=前i件物品,w=可用容量 c(i)=第i件物品容量,v(i)=第i件物品价值
对该公式不明白的可以参考我前面写的0-1背包问题DP
所以,我们很容易推导出完全背包问题的状态转移公式:

    B(i,w) = max( B(i-1,w) ,B(i-1,w-c(i)*k)+v(i)*k )      1=<k<=[V/c(i)] ,V为总可用容量,是w的最大值  

如此,我们可以模拟0-1背包问题写一个三层嵌套循环,然而写起来并不优美,这个式子其实可以再简化,我们推导一下:

  1. B(i,w) = max( B(i-1,w) ,B(i-1,w-c(i)* k)+v(i)* k ) :1=<k<=[V/c(i)] 我们观察B(i-1,w-c(i)* k)+v(i)* k 让 k=k'+1,或者你也可以取k=x+1,k=y+1都行,k'只是一个新的系数表示
  2. 这样一来,B(i-1,w-c(i)* k)+v(i)* k :1=<k<=[V/c(i)] 转换到<==> B(i-1,w-c(i)-c(i)* k')+v(i)* k'+v(i) :0=<k'<=[V/c(i) -1]
  3. 另外(1)式可以表示为:B(i,w) = max( B(i-1,w-c(i)* k)+v(i)* k ) :0=<k<=[V/c(i)]
  4. 同样 B(i,w-c(i)) = max( B(i-1,w-c(i)-c(i)* k)+v(i)* k ) : 0=<k<=[V/c(i)-1]
    观察一下,(2)式的右边和上面这个(4)式的右边是一摸一样的,所以得到了简化式
    B(i,w) =max( B(i-1,w), B(i,w-c(i)) + v(i))
    时间复杂度减少了,因为少了一个嵌套循环

还可以优化下空间复杂度。就像0-1背包问题一样,我们做一维滚动数组优化。因为B(i,w)仅仅依赖于B(i-1,w)和B(i,w-c(i));
最终得到 B(w) =max( B(w), B(w-c(i)) + v(i)) 1=<k<=[V/c(i)]

伪代码:

请注意for v = c[i] ... V 这和0-1背包问题是反向的因为B(i,w)用到了B(i,w-c(i));新值哦
for v = 0 ... V do B[v] = 0
    for i = 1 ... N do
      for w = c[i] ... V do
          B[w] = max{B[w], B[w-c[i]] + v[i]}

二维转一维你需要了解一下滚动数组这个东西,然后完全背包的二维公式是 B(i,w) =max( B(i-1,w), B(i,w-c(i)) + v(i)) ,下标有i代表的都是新值,有i-1代表的都是旧值,转成一维后是 B(w) =max( B(w), B(w-c(i)) + v(i)) ,当然如果要理解顺序问题的话得这么写: B(w)新 =max( B(w)旧, B(w-c(i))新 + v(i)) ,你想下x=max(x,y)这个式子,y对应B(w-c(i)),x是B(w)。w-c(i)比w小,所以要先处理小的,循环从小往大更新

上Java代码:


/**
 * @author  JaJIng
 */
class KnapSack{
    private static final int N = 5;//商品种类
    private static final int C = 20;//总可用容量
    private static final int w[]={2,3,4,5,9};  //每个商品容量
    private static final int v[]={3,4,5,8,10}; //每个商品价值

    public static void main(String[] args) {
        KnapSack knapSack = new KnapSack();
        int bfull[] = knapSack.callFull();
        System.out.println(bfull[20);

    }
     //完全背包  ...
    public int[] callFull(){
        //计算用
        int B[] = new int[C+1];
        for(int n=0;n<N;n++){
            for(int c=w[n];c<=C;c++){
                B[c] = Math.max(B[c],B[c-w[n]]+v[n]);
            }
        }
        return B;
    }

相关文章

  • 完全背包问题(动态规划法-DP含一维滚动数组优化)

    完全背包问题:有n个重量分别为{w1,w2,…,wn}的物品,它们的价值分别为{v1,v2,…,vn},给定一个容...

  • 0-1背包问题(动态规划法-DP含一维滚动数组优化)

    0-1背包问题:有n个重量分别为{w1,w2,…,wn}的物品,它们的价值分别为{v1,v2,…,vn},给定一个...

  • 10.28 - 九章高级算法班题目大总结(5,6课)

    课程5: dp问题1,滚动数组优化,博弈类,记忆化搜索 Longest Increasing Continuous...

  • DP小结

    DP种类 线性DP 区间DP 树形DP 背包DP01背包满背包完全背包(转成01背包) 例子:线性动规:拦截导弹,...

  • 各种背包问题

    0-1背包我比较熟悉,二维dp,通过观察方程可以优化成1维dp,不再赘述 完全背包跟0-1背包的区别是每种型号的物...

  • 01背包问题及滚动数组优化空间

    前言 小M公司年会运气爆棚中奖,老板说给你一个容量w的蛇皮袋,去奖池里愉快的捞吧。奖池里的商品都独一份。袋子能装多...

  • 背包问题整理

    背包问题整理帖,更新中..这里物品的2种属性我这样描述: 花费,亦负重,为w[]数组。价值为v[]数组。dp[i]...

  • dp背包问题

    1、说明 leetcode做了几十道动态规划的题目,大部分都是参考别人的解法进行解答,对动态规划的理解还是不到位,...

  • 动态规划常见面试题

    子序列类型编辑距离 最长递增子序列 最大子数组 最长公共子序列 背包问题0-1背包问题 子集背包问题 完全背包问题...

  • 背包九讲学习笔记

    从上到下顺序遍历 01背包问题 使用二维数组 01背包问题 空间复杂度优化 使用一维数组 重点:此处必须从后往前遍...

网友评论

    本文标题:完全背包问题(动态规划法-DP含一维滚动数组优化)

    本文链接:https://www.haomeiwen.com/subject/npqabqtx.html