NOIp2019前dp专题题解1.0
luogu1373 小a和uim之大逃离:暴力dp的话就是记\(dp_{i,j,p,q,0/1}\)表示当前在\((i,j)\),第一/二个人的数模\(k+1\),且当前轮到了第一/二个人的方案数。优化的话考虑答案统计\(p=q\)的方案数,那么可以把那两维省掉直接记两者差值,时间\(O(NMK)\)
luogu1220 关路灯 :注意到每次所有关掉的灯必然是一个连续区间,且人一定站在区间的两端,于是记\(dp_{i,j,0/1}\)表示已经关掉区间\([i,j]\)的灯,人站在最左/右端的最小花费,预处理出除掉每个区间外的所有灯的每一秒的花费,总时间\(O(n^2)\)
luogu1156 垃圾陷阱:记\(dp_{i,j}\)表示前\(i\)堆垃圾,当前堆到了高度\(j\)的最大血量,转移的话考虑当前这一堆是吃掉还是堆起来,求解答案的话先找到\(dp_{i,m}\)有值的时候\(i\)的最小值,否则就是\(dp_{i,j}\)+第\(i\)堆垃圾出现时间的最大值
luogu1273 有线电视网:树形背包模板题,把用户支出视为正,每条边花费视为负直接背包,时间是\(O(n^2)\)(好像还有个log吧不记得了反正2500能过就对了)
luogu1169 [ZJOI2007]棋盘制作:悬线法模板题,然而也可以写单调栈,时间复杂度\(O(nm)\)
luogu2577 [ZJOI2005]午餐:一个比较显然的贪心是我们把吃饭时间长的放到前面先行考虑,之后用一个类似于背包的设计状态,记\(dp_{i,j}\)表示前\(i\)个人已经完成了,其中第一组打饭时间为\(j\)的最小吃完饭时间,依旧是枚举当前人放在哪一组进行转移
luogu2051 [AHOI2009]中国象棋:问题等价于每一行和每一列放不多于两个炮的方案数,按照套路我们按行转移,同时为了兼顾列的条件,我们记\(dp_{i,j,k}\)表示前\(i\)行,有\(j\)列有\(1\)个炮,有\(k\)列有两个炮的方案数,转移考虑第\(i\)行放0/1/2个炮,对每一种情况还要分它放在有0/1/2个棋子的列,时间\(O(nm^2)\)
Knapsack 2:直接对体积做背包显然会超时,我们需要将背包dp的状态定义由“相同体积的最大价值”转化成“相同价值的最小体积”,由于价值很小这样dp是可行的
Sushi:记\(dp_{i,j,k}\)表示剩下\(i\)个\(1\),\(j\)个\(2\),\(k\)个\(3\)时吃完的期望,注意到每次掷骰子掷到有寿司的期望次数是\(\frac{n}{i+j+k}\),先加上这个次数后再分类讨论三种情况,当然也可以列出掷出吃不到寿司的情况的期望之后移项解方程,实现的话当然是记忆化搜索了,时间\(O(n^3)\)
hdu6662:把每个点的点权看做\(a_i-b_i\),让这个问题变成第一个人最大化\(\sum a_i-\sum b_i\),另一个人要最小化这个值,记\(g_{i,0/1}\)表示当前在点\(i\),只考虑向下走,当前取点\(i\)的是先/后手的差值,\(f_{i,0/1}\)表示在\(i\)点的是先/后手,强制下一步往父亲走的差值,先找\(g\)在找\(f\),为了转移\(f\)需要储存\(g\)的最大/次大/最小/次小值,同时特判只有一个儿子的情况,代码在这里
luogu3804:记\(f_i\)为\(1-i\)已经放好了且必须在\(i\)放一个时的最大数量,考虑找到转移点的范围,记这个范围为\([L_i,R_i].\)对于限制\([l,r]\),转化成\([l,r]\)中至少有一个且至多有一个,对于至少有一个,也就是\(L_{r+1}=max(l,L_{r+1})\);对于至多有一个,也就是\(R_r=min(R_r,l-1)\),最后对\(L_I\)取前缀\(max\),对\(R_i\)取后缀\(min\),单调队列优化即可
CF998F:记\(f_{i,j}\)为在位置\(i\)拿第\(j\)把伞的时候的最小花费(\(j=0\)则未拿伞),转移分三种:1)之前拿了伞但是现在丢掉伞 ;2)一直拿着之前的伞;3)捡起一把伞;分类转移即可