AT_dp 26 题

AT_dp 26 题

A.Frog 1#

直接 dp。设 fi 表示调到石头 i 的最小费用,则有

fi=min(fi1+|aiai1|,fi2+|aiai2|)

B.Frog 2#

上一题的升级版,同样设 fi 表示调到石头 i 的最小费用,则有

fi=minj=iki1fj+|aiaj|

C.Vacation#

fi,0/1/2 表示第 i 天游泳/捉虫/写作业能获得的最大幸福值,则有

fi,0=max(fi1,1,fi1,2)+ai

fi,1=max(fi1,0,fi1,2)+ai

fi,2=max(fi1,0,fi1,1)+ai

D.Knapsack 1#

01 背包。设 fi,j 表示前 i 个物品组成体积为 j 的背包的最大价值,则有

fi,j=max(fi1,j,fi1,jwi+vi)

可以将 i 这一维去掉,则变为

fj=max(fj,fjwi+vi)

注意:j 要反向枚举,因为我们在更新 fj 的时候是用的是原本的 fjwi

E.Knapsack 2#

fi,j 表示前 i 个物品组成价值为 j 的背包的最小体积,则有

fi,j=min(fi1,j,fi1,jvi+wi)

可以将 i 这一维去掉,则变为

fj=max(fj,fjwi+vi)

同上,j 也要反向枚举。

F.LCS#

fi,j 表示字符串 s 的前 i 位和字符串 t 的前 j 位的最长公共子序列长度,则有

fi,j={max(fi1,j,fi,j1,fi1,j1+1),si=tjmax(fi1,j,fi,j1),otherwise

现在还要求出最长公共子序列,于是可以从 fn,m 倒推回 f1,1,并记录最长公共子序列。

G.Longest Path#

DAG 上求最长路。设 fi 表示到点 i 的最长路,则有

fv=minuv(fu+1)

H.Grid 1#

fi,j 表示到位置 (i,j) 的方案数,则有

fi,j={0,si1,j=si,j1.fi1,j,si,j1.fi,j1,si,j1.fi1,j+fi,j1,otherwise

I.Coins#

fi,j 表示前 i 个硬币,有 j 个朝上的概率,则有

fi,j=fi1,j×(1pi)+fi1,j1×pi

可以将 i 这一维去掉,则变为

fj=fj×(1pi)+fj1×pi

同理,j 也要反向枚举。

J.Sushi#

先考虑倒推。

fi,j,k,l 表示剩0/1/2/3个寿司的盘子有 i/j/k/l 个,变成输入状态所需的期望步数,则有,

fi,j,k,l=1+infi,j,k,l+jnfi+1,j1,k,l+knfi,j+1,k1,l+lnfi,j,k+1,l1

整理得:

ninfi,j,k,l=1+jnfi+1,j1,k,l+knfi,j+1,k1,l+lnfi,j,k+1,l1

fi,j,k,l=nni+jnifi+1,j1,k,l+knifi,j+1,k1,l+lnifi,j,k+1,l1

因为 i+j+k+l=n,所以可以将 i 的一维去掉,则有

fj,k,l=nj+k+l+jj+k+lfj1,k,l+kj+k+lfj+1,k1,l+lj+k+lfj,k+1,l1

K.Stones#

fi 表示有 i 个石头时是否有必胜策略,则有

fi={1,jn,fiaj=00,otherwise

L.Deque#

区间 dp。设 fl,r 表示剩余 lr 之间的数的最大差值,则分为两种情况:

  1. (nlen)mod2=0,即太郎先手,则有

    fl,r=max(fl+1,r+al,fl,r1+ar)

  2. (nlen)mod2=1,即次郎先手,则有

    fl,r=min(fl+1,ral,fl,r1ar)

M.Candies#

fi,j 表示前 i 个人分 j 个糖果的方案数,则有

fi,j=k=0min(ai,j)fi1,jk

然后可以利用前缀和预处理出

sumi,j=k=0jfi,k

则可以优化为

fi,j=sumi1,jsumi1,jmin(ai,j)

N.Slimes#

区间 dp。设 fl,r 表示区间 lr 之间合并的最小代价,则有

fl,r=min(fl,k+fk+1,r)+i=lrai

O.Matching#

状压 dp。设 fi,s 表示前 i 个男性和女性集合中状态为 s 的匹配,转移枚举第 i 个男性与哪一个女性匹配,则有

fi,s=jsfi1,sj

P.Independent Set#

树形 dp。设 fi,0/1 表示第 i 个节点染成白/黑色,子树内的染色方案,则有

fi,0=jsonifj,0+fj,1

fi,1=jsonifj,0

Q.Flowers#

fi 表示以 i 结尾的最大权值和,则有

fi=maxj<i,hj<hifj+ai

可以用权值树状数组优化,设树状数组的 ti 表示满足 hj=i 的最大的 fj 即可。

R.Walk#

fi,j,t 表示从 ij 的路径中长度为 t 的路径条数,则有

fi,j,t=fi,k,t1×fk,j,1

然后发现它类似于矩乘的式子,则可以用矩乘优化。设 ft 表示长度为 t 时的矩阵,则有

ft=ft1×f1=f1t

S.Digit Sum#

fi,j 表示前 i 位在任意填的情况下,模 m 的值为 j 的方案数,则有

fi,j=fi1,(jk)modm

然后设 gi,j 表示前 i 位填数不能超过 n 的情况下,模 m 的值为 j 的方案数,则有

gi,j=gi1,(jnumi)modm+k<numifi1,(jk)modm

T.Permutation#

fi,j 表示填充前 i 位,且第 i 位上的数为 j 的方案数,则有

fi,j={k<ifi1,k,si=<k>ifi1,k,si=>

然后前缀和优化即可。

U.Grouping#

fs 表示集合为 s 的物品分组的最大得分,则可以分成两个集合转移,或直接计算,即

fs=maxtsft+fst

V.Subtree#

假设当前的根为 rt,那么可以设 fi 表示 i 的子树内 i 为黑色的黑色连通块方案数,则有

fi=jsoni(fj+1)

所以 rt 的答案为 frt。但若对于每个点都这么做,会达到 O(n2) 的时间复杂度,所以考虑换根 dp。

假设当前已经求出 i 的父亲 fa 的答案为 gfa,则有

gi=fi×gfafi+1

其中 gii 的答案。

但是因为有模数,所以不能用除法,要预处理前缀积与后缀积,然后直接相乘。

W.Intervals#

fi,j 表示前 i 个位置,最后一个 1 在 j 位置的最大分数,则有

fi,j={fi1,j+lkj,rk=iak,j<imaxfi1,k,j=i

观察到有很多 f 之的更新都用到了同一个命令,而且我们发现每一个命令影响的是一个区间,所以我们可以将 f 值丢到线段树上,然后进行区间加。

而对于 i=j 的更新时在 [1,i1] 中取最大值,所以还要进行额外更新。注意到 i 及其后面的尚未更新,所以可以调用全局最大值。

X.Tower#

一眼背包。先排序,若 i 要在 j 的上方,则把 i 放在 j 的上方的剩余空间要大于把 j 放在 i 的上方的剩余空间,则 sjwi>siwj。移项得,si+wi<sj+wj

fi,j 表示前 i 个箱子,重量和为 j 的最大价值,则有

fi,j=max(fi1,j,fi1,jwi+vi)

i 这一维去掉后,则有

fj=max(fj,fjwi+vi)

易得 j 也要反向枚举。

但重量和是 107 级别的,仍需优化。

可以发现重量和一定会小于等于 si+wi,所以可以优化为 104 级别。

Y.Grid 2#

首先,易得从 (x1,y1)(x2,y2) 的路径方案数为 (x1+y1x2y2x1x2)

fi 表示到达第 i 个障碍,且不经过其他障碍的方案数,则有

fi=(xi+yi2xi1)fj×(xi+yixjyjxixj)

如果把点 (h,w) 看做第 n+1 个障碍,则答案就为 fn+1

Z.Frog 3#

fi 表示跳到石头 i 的最小花费,则有

fi=min(fj+(hihj)2+C)

暴力拆平方得

fi=fj+hi22hihj+hj2+C

整理得

fj+hj2=2hihj+fiC

现在想要让截距最小,所以可以对点 (hj,fj+hj2) 维护下凸壳。

作者:liuir

出处:https://www.cnblogs.com/liuir/p/18002803

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   LIUIR  阅读(13)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示