Dynamic Programming
by prime21
NOIp篇
既然都说了是NOIp篇,大概就是一些很简单的东西咯.

背包dp
- 背包dp可以说是常见的模型。比如:01背包,多重背包,完全背包。也许很多名词你不怎么熟悉。但是背包你一定是会的。
- noip2014就考了一道背包dp(愤怒的小鸟)。也考了其简单优化。
Warm Up
Tgop的背包
众所周知, tgopknight是壕。他心血来潮组了一直足球队。
现在他正在为队员们买背包而犯难。tgopknight有数不尽的钱,不过我们可以假设有M亿元。作为美学大师的tgop,定义了美观度。他的手下现在选了N个全黄金镶各种宝石的背包。第i个背包的价格是Mi亿元,美观度是Bi。当然tgop是一个十分任性的土豪,买第i个背包的时候,若手上的钱不足Ti亿元,她就不会买这个背包了。聪明无比的你,能否求出 tgop可以得到的最大美观度呢?
solution
如果作为一道考场题感觉并没有什么难度。只要考虑按几种方式排序然后看是否可以和暴力拍上就好了。然后发现最后的做法是:将T-M从小到大排序然后dp就可以了。
proof:
我们先来考虑一个问题,最少需要多少钱才能买下全部东西。
对于一种给定的排列,买第i个物品需要的最少货币数为Ai
至此很明显的能够看出,把T-M大的值放在前面选,得到的A1才会尽可能的小。想得到更严谨的证明可以考虑排序不等式。
树形dp
- 树形dp也是常见的dp类型
- noip2014,day1,鱼唇的我第二题竟然就是用的树形dp(好像干了什么不得了的事情就MLE了)
- 大体上来说树形dp一般是在dfs的时候dp的。然而也有一些大爷是用for循环虐树形dp的。[zzj大爷]
Warm Up
tgop的party
众所周知, tgopknight是壕。他心血来潮组了一直足球队。
在tgop为老板的这家足球公司里存在上下级关系,且保证每一个人只有一个上司,tgop先生是没有上司的。介于tgopknight的软妹子币多得花不完,她办了一场party,她认为在邀请名单中出现了一个人以及他的上司,这个party就是不愉快的。作为知心姐姐的tgop,给每一个人定义了一个欢乐值,第i个人个欢乐度就是Fi,她想知道,这场party的最大欢乐度是多少。
solution
一道简单的树形dp,分类即可。没什么好说的。。
Medium
砍树
“光头强又在砍树了!”在家里看《熊出没》的prime21的妹妹这样说。
现在问题来了,给定一颗无根树T。我们定义如果一颗子树是好的,则有可以通过断开不超过k条边得到它。
现在prime21想知道,对于给定的T和k,有多少棵树是好的。节点个数不超过100.
solution
- 论一个鱼唇的不能再离谱一点的想法:出这道题的时候本来是想当xdy说的A题的。结果发现并不能直接统计度数组合计数2333.
- 其实还是一道sb题。和常见的树形dp一样,我们令f[u][k]表示与根u相连的已经断开k条边的答案,乘法原理转移即可。
- 注意在最后统计答案的时候与根不相连的要多砍一条边
状压dp
- 状压dp的全称是状态压缩dp。事实上状压dp并非是一种特定的模型,而是由于状态过于复杂,我们需要通过特殊的方式进行表示,即状态压缩。
- 常见的状压方式有:二进制,康托展开,BFS
Warm Up
tgop的球队
众所周知,tgopknight是壕。他心血来潮组了一直足球队。
现在他的球队要参加宇宙杯。一共有2^N(N<=16)支球队参赛,由于参赛球队过多,宇宙杯只有淘汰赛。
正所谓运筹帷幄,决胜千里,tgopknight大爷得到一张表,表的第i行第j列表示的是第i只球队与第j只球队打,第i只球队是否会赢(Y--表示赢,N--表示输)。
淘汰赛可以用如下方式表示:
可以发现,对于不同的起始排列,最后获胜的球队将会不同,tgop想知道对于所有球队而言,每只球队获胜对应的排列数是多少
solution
1.很简单的题直接状压dp,即可。如果超时?怪我咯?这样做的复杂度是:
2.还真的可能超时。最后一次转移强行暴力即可。一看就是你没有经历一些刻骨铭心的东西啊。复杂度
Easy
手办
prime21的手办并不是很多,今天他买了一个新手办。
由于prime21喜欢的角色并不多,所以他可能买了同一个角色的几个手办,只是高度有所不同。
现在prime21把所有手办排成一排,这个排列有点长。排列的长度为N(N<=1000),prime21一共有k种手办[每一个人物算一种](k<=7),给你排在第i的手办的高度Hi,和类型KINDi,现在他想知道完美手办子序列有多少个?一个手办子序列是完美的,当且仅当所有种类都在子序列中出现过一次,且这个子序列中每一个手办的高度都是递增的。
solution
- 同样是没什么难度的状压dp,大家理性愉悦就好。如果是最长的,大约可以变出个n log n算法..
- 其实考虑计数问题依然可以搞个 n log n 记录一个 dp关于h的树状数组即可。
- 然而对于k种物品必须出现,你可以尝试容斥/状压。复杂度相同,容斥空间消耗更小,速度更快。
Advance
果然noip,难度还是太水了。
再讲一点稍微有难度的东西?
论如何把dp水题变得稍微难一点
- 强行加一点维护的东西,比如开始的有限制的01背包,以及有限制的 IS问题。
- 加一些算法:二分转用dp判定,cdq+dp,dp+dfs转移,特殊的状压技巧
- 强套数据结构:维护凸壳,线段树,后缀数据结构,平衡树。
- 发现方程的一些特性,四边形不等式,斜率优化,单调性dp,SPFA优化dp。
玄幻?一个迷惑你眼睛的转移方程
不管有没有迷惑你,反正我开始时被迷惑了。已知如下转移方程,对于给定n,m,求dp[n][m]。其中有dp[0][0]=0。
直接模拟就是N^2暴力,如何优化?
优化个鬼啊?你打表看看。
小剧场结束,马上转入正题。^_^
还是背包dp!
- 是的。你没有看错,这里我们还是讲背包dp。背包dp任然有存在优化之处。
- 背包dp通常也可以套在一些奇怪的模型里面出现
背包优化
- 01背包可以空间优化
- 如果单单按照01背包的套路暴力解决多重背包和完全背包问题时间复杂度较高,往往不能取得满分。
- 下面稍微讲一下优化。
完全背包
1.我们考虑完全背包的dp方程:
2.其实我们可以改写此方程:
空间优化:对于01背包,我们每次倒序枚举剩余空间,不需要额外的一维来存储上一次的答案。
实际上就是在递推的时候顺序进行,即可以利用之前已经选了该物品的背包继续放该物品
多重背包
相比之下多重背包的限定了放置个数,优化难度更大,但是我们要相信,算法是可以优化的!
level 1 二进制优化
我们原有的思想是把一个可以使用k次的物品,拆分成可以k个只能使用一次的物品。
然而我们可以进一步思考?对于1~k中的所有可能情况,是否用更好的表示方法表示所有的信息呢?
我们考虑用形如 的数的0,1组合恰好可以表示1~k之间的所有整数。所以我们考虑可以拆分成 个物品,每个物品的权值是原有基础上的 ,最后一个是 。其中m是能满足 的最大整数。
level 2单调队列优化
通过二进制优化之后的多重背包的时间复杂度是 ,但我们期待所有的背包问题,都可以在 解决。
单调队列优化
Dynamic Programming
By prime21
Dynamic Programming
Dynamic Programing
- 2,352