zoukankan      html  css  js  c++  java
  • 我对背包的理解

    背包之前了解的太肤浅了,最近又重新看了一遍,记录一下理解的心得:

    参考:http://www.cppblog.com/tanky-woo/archive/2010/07/31/121803.html

    http://blog.csdn.net/wumuzi520/article/details/7021210很详细

    01背包

    状态转移:f[i][j] = max{f[i][j], f[i-1][j-v[i]]+w[i]}关键就是取或不取,两重for循环,都从0开始

    一维数组:f[j] = max{f[j], f[j-v[i] ] + w[i]},这里内循环也就是体积是逆序的,这个得好好理解

    因为f[j] 表示的是前i个情况下j的价值量,它的值由前i-1状态决定,就是二维的那个转移方程,也就是每循环一次,f这个一维数组的内容就是当前第i个物品,在每一种体积下的最大容量,假设,内循环按照从小到大,那么前面的值就会改变,直接假设循环到了最后最大容量那个,而此时f[j-v[i]]已经更新完了,不是前i-1种状态了。

    完全背包:

    状态转移:f[i][j] = max{f[i][j] , f[i-1][j-k*v[i]] + w[i]} k是个数

    一维数组:f[j] = max{f[j], f[j - v[i]] + w[i]}   //解设一种物品个数取两个,就是在取一个的基础上再加一的;

    这个内循环是正序,因为f[j]表示的是第i中物品在体积为j下的最大最,因为你不知道到底i中物品取第几个,所以你先从体积最小开始,如果j能够取两个,那么就在取一个f[j-v[i]]的基础上再取一个+w[i],直到循环到最大的容量,此时的f【】就是对应每个体积下的最大价值;

    多重背包:

    个数有限制,可以来三个循环,第一层是第i中物品,第二层是个数,第三层是体积;其实这就转成01背包了,

    1  for(int i=0; i<nKind; ++i)
    2             for(int j=0; j<bag[i]; ++j)
    3                 for(int k=nValue; k>=value[i]; --k)
    4                     if(nMultiplePack[k] < nMultiplePack[k-value[i]]+weight[i])
    5                         nMultiplePack[k] = nMultiplePack[k-value[i]] + weight[i];

     采用二进制转换:

     假如给了我们 价值为 2,但是数量却是10 的物品,我们应该把10给拆开,要知道二进制可是能够表示任何数的,所以10 就是可以有1,2, 4,8之内的数把它组成,一开始我们选上 1了,然后让10-1=9,再选上2,9-2=7,在选上 4,7-4=3,而这时的3<8了,所以我们就是可以得出 10由 1,2,4,3,来组成,就是这个数量为1,2,3,4的物品了,那么他们的价值是什么呢,是2,4,6,8,也就说给我们的价值为2,数量是10的这批货物,已经转化成了价值分别是2,4,6,8元的货物了,每种只有一件哎!!!!这就是二进制优化的思想。

    那为什么会有完全背包和01 背包的不同使用加判断呢?原因也很简单啊,当数据很大,大于背包的容纳量时,我们就是在这个物品中取上几件就是了,取得量时不知道的,也就理解为无限的啦,这就是完全背包啦,反而小于容纳量的就是转化为01背包来处理就是了,可以大量的省时间。

  • 相关阅读:
    利用Python和webhook实现自动提交代码
    Python threading 单线程 timer重复调用函数
    Python requests 使用心得
    openresty实现接口签名安全认证
    使用jedis面临的非线程安全问题
    记一次线上升级openresty中kafka版本产生的多版本兼容问题
    mysql中走与不走索引的情况汇集(待全量实验)
    Elasticsearch深分页以及排序查询问题
    IO多路复用:Redis中经典的Reactor设计模式
    Netty在Dubbo中的使用过程源码分析
  • 原文地址:https://www.cnblogs.com/zhaopAC/p/5042854.html
Copyright © 2011-2022 走看看