• Zeroonepack coming~^.^


    今天抓的四道DP做完了==三道是用背包做的,突然想起来背包知识点总结还没做~反正时间还早。。把01背包和完全背包小结了吧~~福利来啦~~噶呜~

    01背包:

    基本思路:

        01背包问题是最广为人知的动态规划问题之一,介绍01背包之前,先来看一个引例:

        有N件物品和一个容量为V的背包。第i件物品的体积是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大。

        这是最基础的背包问题,特点是:每件物品只有一件,选择放或者不放。

        由以上的特点,我们可以写出状态转移方程:
              f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]} 
        这个方程非常重要,基本上所有跟背包相关的问题的方程都是由它衍生出来的 
         如果不放第i件物品,那么问题就转化为“前i-1件物品放入容量为v的背包中”,
         价值为f[i-1][v];
         如果放第i件物品,那么问题就转化为“前i-1件物品放入剩下的容量为v-c[i]的背包中”,
         此时能获得的最大价值就是f[i-1][v-c[i]]再加上通过放入第i件物品获得的价值w[i]。

    优化空间复杂度:

        以上方法的时间空间复杂度为O(VN);能优化到O(N);该思路如何实现呢?

         主循环肯定是(1~N),如果用一个数组f[0~V]能不能保证第i次结束后f[v]中表示的就是我们定义的状态f[i][v]呢?

         f[i][v]是由f[i-1][v],f[i-1][v-c[i]]两个子问题递推而来的,能否在推f[i][v]的时候也能够得到f[i-1][v],f[i-1][v-c[i]]的值呢?事实上,只要我们每次主循环中以v=V~0

         的顺序推f[v],就能保证f[v]是f[v-c[i]]保存的是状态f[i-1][v-c[i]]的值。

        伪码:
        for i=1..N 
          for v=V..0 
            f[v]=max{f[v],f[v-c[i]]+w[i]};

        为了方便使用,写出01背包的过程:

    zreoonepack(cost,weight)//cost和weight分别表示这件物品的费用和价值

        for v:V~cost

            do f[v]=max(f[v],f[v-cost]+weight).

    有了这个过程,01背包的伪码就写成啦:

        for i:1~N

            do zreoonepack(c[i],w[i]);

    初始化细节问题:

        在求最优解背包的问题中,要特别注意题目的问法~:是否要求恰好装满背包!!

        如果是要求恰好装满背包,在初始化时除了f[0]=0外,其他f[1~V]均设为负无穷~~

        若没有要求,初始化时只需要将f[0~v]全部设为0.

        下面简述原因

            如果要求恰好装满背包,那么此时只有容量为0的背包可能被价值为0的nothing恰好装满,其他容量背包均无合法解。

    一个常数优化:

        for i=1..N 
          for v=V..0 
            do。。。

    可以将这个循环的下限进行改进:由于只需要最后f[v]的值,倒推前一个物品,其实只需要知道f[v-w[n]]即可,所以代码可以改成

         for i=1..N 

            do bound:max(V-sumw[i~n],c[i])
          for v=V..to bound
            do。。。

    这么详细的讲解,小盆友们都会了吧?~噶呜~~

  • 相关阅读:
    用 Java 爬美女图片,厉害了。。
    Java-Stream流方法学习及总结
    Swagger3 更新配置详解
    一、MySQL下载和安装
    hack(兼容IE及浏览器常用的写法)
    css常用单位
    Ps使用 和精灵图的制作
    HTML5
    JS面向对象
    seajs与requirejs
  • 原文地址:https://www.cnblogs.com/PJQOOO/p/3902619.html
Copyright © 2020-2023  润新知