背包问题 七七八八

暂时的总结

 

  1. 01背包:n种物品和体积为m的背包,每种物品只能选1次,问能装的最大价值:

                    f[i][j] = f[i-1][j-v]+w,f[i-1][j](以最后一步选与不选来划分集合)

                   观察式子可知,f[i][j]只能由f[i-1]的状态转移而来,因此只需要保存f[i]与f[i-1]两个状态.

                   01背包应用举例: Cow Exhibition POJ - 2184 (非常规思路建立01背包模型,根据实际需求,j定义为不同含义求的答案方便程度不同)

        2.完全背包:n种物品和体积为m的背包,每种物品只能选无限次,问能装的最大价值:

                   f[i][j] = f[i][j-v]+w,f[i-1][j](以最后一步选与不选来划分集合)

                   对于每一个物品,完全背包本需要每个物品枚举m/v次,看装几个最优,但是这个f[i-1][j-k*v]+w*k可以被f[i][j-v]代替.

                   完全背包应用举例:求最大线性无关组. P5020 [NOIP2018 提高组] 货币系统

       3.多重背包:n种物品和体积为m的背包,每种物品只能选s次,问能装的最大价值:

                   f[i][j] = max(f[i-1][j],f[i-1][j-v]+w...f[i-1][j-sv]+sw)

                   对于每一个物品,最多选min(m/v,s)次.需要在状态转移中枚举次数.暴力时间复杂度过大,因此需要优化:

  •           常见优化思路: 二进制优化 对于每个物品,将它的数量s化为二进制,因为任何自然数都可以由二进制表示,所以一定可以枚举到所有的数量情况.时间复杂度O(m*nlog2s)
  •           常见优化思路: 单调队列优化 由上面的状态转移方程可以发现能转移到f[i][j]的子状态都与f[i][j]%v同余.所以转化而成了一个大小为s+1的窗口求最值.时间复杂度:O(n*m)

                 多重背包应用举例:Charlie's Change POJ - 1787 (多重背包题目做的少,以后做多了题会重新改)

      4. 混合背包:n种物品和体积为m的背包,每种物品有的可以选1次,有的无限次,有的最多s次,问能装的最大价值:

                 实际可以全部转换为多重背包:01背包->只能取1次

                                                                 完全背包->只能取m/v次

                 由上面所有背包的状态转移方程可以发现:f[i][j]的最值与f[i-1]是什么类型无关,只与它的最大值有关.因此可以直接套多重背包的模板.

                 混合背包应用举例:P1833 樱花

      5.分组背包:n组物品,每组有s个物品,每组只能取一个,求最大价值.

                 f[i][j] = max(f[i-1][j-v[i][k]+w[i][k],f[i][j]).

                 对于每组枚举取哪一个,但是注意要讲究循环顺序.显然i是最外层循环,但j必须是第二层循环,最后才是k.如果先枚举k,无法保证每组只选了一个.

                 分组背包的特点是:每组最后累加为体积m,每组的情况是互斥的

                 分组背包应用举例:P1064 [NOIP2006 提高组] 金明的预算方案

      6.树形背包问题:分组背包问题的延伸

                详情见 AcWing 10. 有依赖的背包问题

                为什么这是分组背包呢?将划分不同子节点的体积看成一个个小组,比如子节点1,2,3.给子节点1划分0,1,2,3,4,5...m体积作为情况,每种情况是互斥的,最后累和是                  父节点的体积,所以可以看成分组背包.

      7.背包问题求最优方案数

                 从这里开始可以将一个个的状态转移看成图论的最短路问题.最优解的方案数就是达到最优解的路径条数.由状态转移方程:

                 f[i][j] = f[i-1][j-v]+w,f[i-1][j].如果f[i-1][j-v]+w取最大值,那么f[i][j]的最优解是cnt[i][j]+=cnt[i-1][j-v].如果f[i-1][j]取最大值,cnt[i][j]+=cnt[i-1][j].如果两者最大值相等就是                     两者都加上.

                 求最优方案数经典应用:Islands and Bridges POJ-2288 (牵扯到了状压dp)

      8.背包问题求具体方案

                同样看成最短路问题,如何求具体方案可以从最优解f[n][m]递推回去,判断f[n][m]是由f[n-1][m]或者f[n-1][m-v]+w转移而来.一般有for循环和dfs两种写法.

                如果是求字典序最小的具体方案,因为我们一般是从结果最优解递推(即f[n][m])但这样不能保证是最优解(不能确定第n个选不选是否为字典序最小)我们推断字典                  序最小,是从i=1开始推断.如果第i个可以取最大值,那么第i个就入选.那么只需要将一般的背包模型第一重循环改为n->1.这样第1个就是最终最优解.

                求具体方案应用:  UVA-323 Jury Compromise

 

估计以后还会更新...背包dp延伸问题实在多...

posted @ 2021-03-28 13:51  acmloser  阅读(66)  评论(0编辑  收藏  举报