zoukankan      html  css  js  c++  java
  • 背包九讲学习

    DD大牛的背包九讲真是神。等我全看懂了回来更博。


    upd

    如果不是我看错了,那一定是神犇讲的太明白了。

    我尝试用几句话概括一下前面部分(P01-P05),每回重新看有些麻烦。

    $cost ightarrow花费,value ightarrow价值$


    01背包

    决策:选或不选,$f[v]$表示v花费可以得到最大价值。则

    $forspace v=V...cost$
    $f[v]=max(f[v],f[v-cost]+value)$

    只能由上一层转移来,所以倒序保证不影响。

    想要恰好$V$就只有$v=0$合法即初始化$f[0]=0$,其他为$-inf$。不需要都赋为$0$。

    所有问题的基础。$O(nV)$


    完全背包

    总是记不住这些名字,就当做是“完全随便拿”的背包吧,,,则

    $forspace v=cost...V$
    $f[v]=max ( f[v],f[v-cost]+value ) $

    类似01,可以同层转移,就这样咯。$O(nV)$


    多重背包

    类似完全背包。加一些限制。是“可以重复多拿”的,但不能太多,每个物品有限制。

    想法是拆成二进制的。比如$13=1+2+4+6$这么拆,不要记错了。

    楼教主“男人八题”那个单调队列的暂时不会,挖坑。


    废话

    一些显而易见的贪心。超过$V$的不能选,完全背包里$cost$又大$value$又小的,不去选ta。


    混合背包

    好像没啥说的,前三个混到一块各做各的该咋做咋做就行。。


    二维花费

    那就二维状态,类比一下就行。则

    $forspace v=V...cost1$

    $forspace u=U...cost2$

    $f[v][u]=max(f[v][u],f[v-cost1][u-cost2]+value)$

    只要不从同一层状态转移过来就好。


    写完感觉好傻啊。

    所以说重点在于泛化物品咋做。

    泛化物品定义成这样:对于你赋给它的每一个花费会获得对应的价值。

    更数学化一些,这是一个函数,定义域为$V$,自变量是花费$cost$,函数值是价值$value$。对于每个$cost$都有一个对应的$value$,如果某个$cost$没有定义,我们可以视之为$-inf$。

    具体来说,比如01背包中的背包,当且仅当赋给它$cost$值时有函数值$value$,其他为$-inf$。

    又如多重背包,我们甚至可以写出解析式:$f[x]=xdiv cost imes value (cost|x)$

    当然啦,我们抽象出这样一个定义又有什么用呢?

    泛化物品可以做加法!!!

    对于两个泛化物品$a,b$,我们把他们加成一个泛化物品$c$,即

    $c[v]=max(a[i]+b[v-i])(0leq ileq v)$

    复杂度$O(V^2)$。

    于是现在再来说刚才没说的分组背包和有依赖的背包。


    分组背包

    物品分成了$k$组,每组内物品只能选一个或不选。

    每组做一次01背包,就可以当做$k$个泛化物品做了。$O(kV^2)$


    (树形)依赖背包

    依赖显然不会存在环,所以普通的依赖也可以转成树形。

    然后通法就是:儿子当做泛化物品,则父亲是儿子之和,递归处理之。

    这里会补上一个代码。


    至此我对背包九讲的理解结束了!!现在看起来真的不是很难懂的东西但却十分巧妙,尤其是用函数的思想将物品转化成泛化物品,让我不得不佩服DD大牛%%%。最后一讲我没有细看,如果有时间我应该会回来更博写一下。


    upd

    树形背包有$O(NM)$做法的啊。所以上面的代码就不补了(已经用那种做法水掉CTSC1998选课了,时间上差了好多顿时不想贴那个的代码了)。

    $dp[i][j]$表示选择了节点 $i$ (及其所有祖先节点) (即根节点到 $i$ 的路径——记作 $Pi$ 上的所有节点),此外再在 $Pi$ 的左侧和子树 $i$ 中选择总体积不超过 $j$ 的物品的最大价值。

    void dfs(int u,int f,int cost)
    {
        if(cost<=0)return ;
        for(int i=0;i<e[u].size();i++){
            int v=e[u][i];
            if(v==f)continue;
            for(int j=0;j<=cost;j++)dp[v][j]=dp[u][j];
            dfs(v,u,cost-b[v]);
            for(int j=b[v];j<=cost;j++)dp[u][j]=max(dp[u][j],dp[v][j-b[v]]+a[v]);
        }
    }
  • 相关阅读:
    阿里云(一)云存储OSS的命令行osscmd的安装和使用
    Zephir入门教程一
    【转载】视频CDN技术原理与流程说明
    博客园页面css样式
    Linux使用imagemagick的convert命令压缩图片、节省服务器空间
    WebSockets Tutorial(教程一)WebSockets简介
    ngx_lua_API 指令详解(四)ngx.exec指令
    Git与GitHub学习笔记(二)提交的一些笔记
    这些万能的文献检索工具,你用了几个?
    干货||科研收藏夹必备35个学术网址
  • 原文地址:https://www.cnblogs.com/orzzz/p/7743056.html
Copyright © 2011-2022 走看看