部分DP总结
一 背包:
背包是比较基础但应用比较广泛的一类DP, 其主要类型包括01背包, 完全背包, 多重背包, 分组背包等;
背包问题条件一般可以化为: 给定n个物品,每一个物品有一个价值,一个代价;
01背包就是在给定上述条件下 (每个物品只能用一次)求代价S以内能得到的最大价值。
01背包可以滚成一维,只不过枚举价值时应倒着枚举;
完全背包就是01背包问题中的每个物品可以用任意多次, 和01背包的唯一区别就是枚举价值正着枚举就行了。
多重背包就是01背包问题中的每个物品最多可以用给定次数次。
对于多重背包问题的解决, 比较直接的思路是在和之前两个一样,不过就是多枚举一个用到的次数 (次数的枚举在物品和价值的枚举之间)。
但是这样复杂度还是比较高的, 我们可以考虑如何优化。
首先, 对于任意一个数k, 它可以拆成几个2的次幂的和;
所以我们把每个物品能用的次数拆分成若干个(每个都是2的多少次幂,和为它本身)吗,直接当01背包转移
这样在转移过程中,对于每一个物品,每个可能的用的次数都会被使用到吗,所以正确性是显然的;
同时,我们也总共只要枚举 sigma (logCi)个物品, 复杂度显然也更优秀了;
分组背包就是有N组物品,每组Ci个物品,每个物品都是和01背包的物品一样的条件;
直接当01背包来做(只不过要多枚举一个组数,同时组数也是第一维状态,同时应注意物品的那层循环在最内层);同样的和01背包一样可以滚掉第一维;
其实单调队列也可用来优化背包,但是我自己都还没学。。。就算了吧~~~~(>_<)~~~~
几道背包的好题:BZOJ4272 挂饰 (01背包), Luogu1537 弹珠(二进制优化多重背包), Luogu1156 垃圾陷阱 (01背包吧。。反正蛮好的);
二、区间DP
区间DP没那么多好讲的, 听Dalao讲区间DP一般难在优化, 然后蒟蒻认为一般区间DP还难在发现他是区间DP(可能是我太水了)。。
直接贴几道好点的题目:Luogu1220关路灯, CF567FMausoleum(可以去Luogu上看宇智波鼬大佬的题解), UVA10559 Blocks (可以去Luogu上看 EMT__Mashiro 神犇的题解);
三、树形DP
怎么说呢 我也可以说刚刚入门啊!
其主要的思想就是先递归DP其子节点,然后回溯时在对此节点进行转移即可。
裸一点树形DP 没有上司的舞会 , 时态同步 。
然后稍微进阶一点的是树形背包 就是在树形DP的形式下做背包问题,实际上也还是离不开上面的思想。
入门的树形背包 选课。
然后上面几道题都是在树上有明确转移方向的,也就是说他的根是给定的。
那么对于不定根的题目呢??
这类暴力的思想是直接对每一个点作为根跑一遍树形DP,那样复杂度是会多一个n的 ,显然不优。
那么怎样来做呢??
实际上这一类问题一般都可以发现一个共性,把他做根的DP值是与把其父亲节点做根的DP值是息息相关的。
仔细思考我们可以发现 ,这之间一定存在这某种递推关系有父节点的DP答案能够推出他的答案,不需要再DP一遍!!
为什么呢??
因为整棵树的结果就可以看成一部分由以它本身为根的子树组成(这是DP出来了的), 另一部分就是剩下的;
在把他换成根后,一部分的贡献已知, 另一部分的贡献就是他父亲的DP值减去它本身的贡献,两部分合起来就是以他为根的答案。
这样的话, 我们只要任意选一点为根跑一遍DP, 在通过遍历树的方法自顶向下递推一下就可以了。
暂时先写这一点点吧 。还有很多类型的DP都没有涉及到,希望以后能抓紧时间补上。