寒假day4 2.5

讲师:钟皓曦,NOI2012Au,from 成都七中

dp

树形dp

核心:在树上做的 dp

给定一棵 \(n\) 个点的树,求这棵树有几个点。

对于树形 dp,第一个维度是 \(f_i\),代表以 \(i\) 为根的子树内的信息(有几个点)

树形 dp 的转移方法是把所有儿子信息整合

所有儿子的 dp 值 \(\rightarrow\) 自己。

转移:\(f_i=f_{son1}+f_{son2}+\ldots +f_{son_n}+1\)

答案:\(f_1\)

树形dp利用dfs实现

给定一棵 \(n\) 个点的树,每条边有边权,定义 \(dist(i,j)\) 代表 \(i\rightarrow j\) 的路径长度,求 \(\sum\limits_{i=1}^n\sum\limits_{j=1}^ndist(i,j)\),数据范围 1e6。

\(f_i\) 代表 \(i\) 这棵子树内的答案。

考虑一条边被经过几次。什么时候会经过这条边?显然,\(i,j\) 一定要一个在外面,一个在里面。

\(f_i\) 代表子树大小,一条边连接 \(i\) 与其父亲的边被经过的次数就是 \(2\times f_i\times (n-f_i)\)。(乘法原理)

注意两个点可以换顺序,所以应 \(\times 2\)

给定一棵 \(n\) 个点的树,有边权,求 \(max_{i,j}dist_{i,j}\),1e6。

其实是求树的直径。

如果边权非负,两点一定都是叶子节点。

\(f_i\) 代表子树内**距离 \(i\) **最远的距离,\(g_i\) 代表次远的距离。

树上路径组成:起点+终点+LCA

答案:\(\max_{1\le i\le n}(f_i+g_i)\),这里做的是枚举 LCA。

如何考虑转移?

画一个数轴,观察当前值 dis 与 \(f_{now}\) \(g_{now}\) 的位置关系。

求树的最大独立集,没有上司的舞会。

最大独立集:选出尽量多的点,使得它们不相邻。

把根节点染成黑色,子节点染成异色,不断染,统计黑白数量,这是错误的,但告诉我们树是二分图。

证明一件事错误是很困难的,但举出反例是容易的

\(f_i\) 代表子树内根节点染色的情况下最大独立集,\(g_i\) 代表不染色的情况下最大独立集。

发现 \(i\) 是否染色,会根据儿子是否染色。

dp中可以把所有想知道的事记到状态里

考虑 \(f_i\) 的转移。

此时儿子肯定都不能选,\(f_i=1+\sum\limits_{k=1}^mg_{son_k}\)

对于 \(g_i\),儿子可选可不选,所以 \(g_i=\sum\limits_{k=1}^m\max(f_{son_k},g_{son_k})\)

ppt 41 P5 poj463

利用上一题的思想。令 \(f_i\) 代表没有士兵,由儿子守护。

对于 \(i\) 点,如果不放士兵,所以要不是儿子保护它,要不然就是父亲守护它,增加 \(h_i\) 代表没有士兵,但是由父亲守护。

对于 \(f_i\) ,至少一个儿子要有士兵。

\(p_{i,0/1}\) 代表前 \(i\) 个儿子,是否有士兵,————————————。

建议看代码,讲的有点快。

树形dp常见手段——将所有儿子信息合并时,往往需要另一个dp辅助合并

\(f_i=\sum\limits_{k=1}^m\)

\(g_i=1+\sum\limits_{k=1}^m\min(f_{son_k},g_{son_k},h_{son_k})\)

\(h_i=\sum\limits^mf_k\)

状压dp

核心思路:把 \(n\) 个数压缩成一个数

二进制状态压缩——只有 0/1 两种取值

ppt 60 P1 吃奶酪

\(n\) 位的二进制数表示每个点是否走过,这个二进制数 \(\le 2^n\)

\(f_{S,i}\) 代表每个点状态集合为 \(S\) 时终点是 \(i\) 的情况下的最小距离。

初始化:一开始把所有值标记成 double_inf\(f_{1,0}=0\)

判断集合中的状态:i&(1<<j)

合并状态:chkmin(f_{1|(1<<k),k},f_{i,j}+dis_{j,k})

把 bool 数组变成一个数

注意最后加答案要走回 \(0\) 号点。

复杂度 \(O(2^N\times N^2)\)

严格复杂度证明

状压的题范围不会很大 \(\rightarrow\) 范围不是很大的题可能会是状压。

ppt 61 P2 P1879

一个格子能不能种草:上一行种没种,这一行有没有相邻的种草。

\(f_{i,j}\) 表示前 \(i\) 行已经种好草,第 \(i\) 行的种草情况为 \(j\) 时的方案数。

枚举下一行的种草情况,统计方案数。

K 国王问题 P1896

与上题的不同——国王数量

多一个条件 \(\rightarrow\) 加一个维度

\(f_{i,j,k}\) 代表前 \(i\) 行种草情况为 \(j\) ,已经用了 \(k\) 个国王的方案数。

剩下一致。

ppt 118 P6 CodeChef LEMOUSE

\(f_{i,j}\) 代表走到 \((i,j)\) 最少老鼠数。

经典题,方格取数。

但是显然不对。

\(f_{i,j,0/1,0/1}\) 代表走到 \((i,j)\) 时,上一步是向右/下,上两步向右/下走。

考虑到被同一只老鼠反复吓到中间过程最多走两步。

复杂度 \(O(4n^2)\)

ppt 124 P9 P2051

放炮要规定一个顺序——一行一行放

讨厌计数题

\(f_{i,j,k}\) 代表放到第 \(i\) 行时,有 \(j\) 列放了 \(0\) 个炮,有 \(k\) 列放了 \(1\) 个炮。

显然,有 \(m-j-k\) 列放了两个炮。

对于第 \(i\) 行,可以放 \(0\sim 2\) 个炮。

\(0:f_{i,j,k}+=f_{i-1,j,k}\)

\(1:f_{i,j,k-1}+=f_{i-1,j,k}\times k,f_{i,j-1,k+1}+=f_{i-1,j,k}\times j\)

对于放两个炮的情况,有三种情况进行转移。

博弈论dp

\(n\) 个点,\(M_{i,j}=0/1\) 代表 \(i\rightarrow j\) 是否右有边,求从 \(1\) 号点出发走 \(t\) 步到 \(n\) 号点的方案数。

怎么又是计数题

\(f_{i,j}\) 代表走了 \(i\) 步走到 \(j\) 的方案数。

\(M_{j,k}==1\rightarrow f_{i+1,k}+=f_{i,j}\)

时间复杂度 \(O(TN^2)\)

另一种写法:\(f_{i,j}=\sum\limits_{k=1}^Nf_{i-1,k}\times M{k,j}\)

范围 \(N\le 100,T\le 10^9\)

dp常见优化技巧:把二维变成三维后利用矩阵乘法优化

\(f_i[1][j]=\sum\limits_{k=1}^Nf_{i-1}[1][k]\times M[k][j]\)

发现 \(f_i=f_{i-1}\times M\)

复杂度 \(O(N^3\log T)\)

用矩阵乘法优化的 dp 题的特点:\(f_i\) 只和 \(f_{i-1}\) 有关;转移系数 \(M\)\(i\) 无关。

复杂度:\(O(n^2\times t)\rightarrow O(n^3\log t)\)

迷路 P4159

本题的不同是存在边权——拆点。

但发现拆完以后存在 \(800\) 个点,会 T。

考虑删去一下无用的边。

发现只有 \(9n\) 个点,可以接受。

有一张 \(n\) 个点的图,给出 \(T\),求从 \(1\) 号点走 \(T\) 步到 \(n\) 号点的方案数,\(M_{i,j}\) 表示从 \(i\)\(j\) 有几条边,\(in_{i,j}\) 表示第 \(i\) 个点的第 \(j\) 个入度,给出 \(in_{i,j},out_{i,j}\)\(N\le 1000,T\le 10^9,r\le 20\)。BZOJ 3583

发现 dp 式子和前面题一样,可恶的计数题

观察到 \(r\) 很奇怪,考虑把 \(r\) 作为突破口。

\(M_{i,j}=\sum\limits_{k=1}^rout{i,k}\times in_{j,k}\)

考虑在读入时更换 in 数组的第一个和第二个维度,看做矩乘。

\(M=out\times in\)

复杂度变成了 \(O(r^3\log T)\),总之很抽象。

发现三道题都是变成第一道题,所以要把未知问题变成已知问题

博弈论dp

给定 \(N\) ,可以将其变为 \(N-1,N-2,N-4,N-8\),谁先变成 \(\le 0\) 谁输。

\(f_i\) 代表数为 \(i\) 时,先手必胜还是必败。

显然,\(f_{-7\sim 0}=1\),是先手的对手把 \(N\) 变成非法了,所以先手必胜。

考虑对 \(i\) 一次操作后的取值,设 \(f_{i-1}=T,f_{i-2}=F,f_{i-4}=T,f_{i-8}=T\),此时显然应该选择 \(i-2\),因为对手必败。

可以发现,所有能转移到的状态中如果存在必败态,则 \(i\) 为必胜态;否则 \(i\) 为必败态。

存在一步操作使得对手必败,则自己必胜;若所有操作使得对手必胜,则自己必败

能用记搜最好用记搜

状态=游戏的状态

表示当前状态是否必胜

转移根据规则操作

要看能否转移到必败态

\(S\),每次减去一个正整数,但不能超过上一轮减去的数的 \(k\) 倍,问必胜/必败。

\(f_{S,i}\),减去 \(i\)

初始 \((x=1,y=0)\),操作:\((1,x+y),(2x,y),(3x,y)\),如果 \(x+y\ge n\) 只能用 \(1\)\(y\ge n\) 输。BZOJ 2798

\(f_{x,y}\) 代表两个数为 \((x,y)\) 时的先手状态。

根据规则转移。发现时空限制不可以,\(O(n^2)\)

发现 \(x\) 一定可以表示成 \(2^{d1}\times 3^{d2}\),将状态变为 \(f_{a,b,y}\)

\(n\) 个数,每个数 \(\le 100\),取数,取完 GCD 变成 1 就输。CodeChef Sereja ans Game

\(f_{i,j}\) 代表取了 \(i\) 个数,GCD 为 \(j\) 时的状态。

转移时,把 \(n\) 个数分为两类,是/不是 \(j\) 的倍数。

在不是倍数的那堆里,一定可以随便选。\(f_{i,j}\rightarrow f_{i+1,\gcd{j,c_k}}\)

另外一堆,随便选也都行(除非 \(i\ge m\)\(f_{i,j}\rightarrow f_{i+1,j}\)

可以感性理解。

\(n\) 个数,每次可以把某一个数变为 \(x-1,x-2,x-4,x-8\),把 \(a_i\le 0\),输

SG 值:对于一个必败态的 SG 值,一定为 \(0\)。一个数 \(i\) 的 SG 值为 \(\operatorname{mex}{\operatorname{SG}(i-1),\operatorname{SG}(i-2),\operatorname{SG}(i-4),\operatorname{SG}(i-8)}\)

SG(1)=0

SG(2)=mex(SG(1))=1

SG(3)=mex(0,1)=2

SG(4)=mex(2,3)=0

\(\operatorname{mex}(z_0,z_1,z_2,\ldots,z_{m-1})\)

先排序,再去重,再用指针求 mex

z[m]=-1,sg[i]=0;
while(z[sg[i]]==sg[i])
    sg[i]++;
return sg[i];

去重前一定要排序

SG(必败态)=0

SG(必胜态)不等于0

SG 定理:\(n\) 个游戏组合在一起的 SG 值,等于每个游戏的 SG 值异或起来

第一类博弈论:针对单个游戏,利用必胜/必败进行 dp

第二类博弈论:针对多个游戏,利用 SG值 进行 dp

Nim 石子游戏问题

选一堆石子,每次对一堆取走至少一个石子。

答案就是看 \(a_1\oplus a_2\oplus\ldots\oplus a_n\) 是否为 \(0\)

所有第二类博弈论问题做法——用 SG值 进行dp or 转换为 Nim

ppt 78 P4

在长度为 \(i\) 的空格子中染第 \(j\) 个,发现 SG(i)=mex(SG(j-3)\(\oplus\) SG(i-j-2))

二类套二类。

ppt 82 P6

发现子游戏互相影响。

在博弈论中,如果操作可以被对手模仿,那这就是没有意义的

答案:\(a_1\oplus a_3\oplus a_5\ldots\) 是否为 \(0\)

对于偶数层的石子,只要先手怎么移,后手就跟着怎么移。

对于奇数层的石子,搬一次后就没有意义了。

关键——状态的设计

最难的——看出这个题要 dp

网络流和 dp 非常容易混淆,两者都属于线性规划问题

状态设计套路——题目中什么量在变化

暑假是出现分水岭的地方,是黄金时期

posted @ 2024-02-05 11:28  BYR_KKK  阅读(16)  评论(0编辑  收藏  举报