题解-luogu-p1273有线电视网

题目链接

背包类树形dp。本题需要运用分组背包模型。

首先定义状态:$f[u][i]$表示以$u$为根的子树上,选择$i$个用户时的最大利润。由于电视公司可能亏本,因此$f$数组应赋极小初值。

可以将选择的用户个数看作背包的容量维度,将获得的利润看作背包的价值维度。可以设计出如下的状态转移:
$$
f[u][i]=\max_{v\in son(u)}{f[u][i-j]+f[v][j]-w}
$$
其中,$v$为$u$的子节点,$w$为这条边的权值。在$u$每个子节点上有许多“物品”,“物品”总数即为以$v$为根的子树上用户的个数;每个“物品”所具有的价值即为其最大利润,即$f[v][j]$。同时不应忽略边权对利润带来的影响。

注意细节处理及边界。代码如下:

题解-luogu-p4516潜入行动

这是一个并不简单的背包类树形dp……

很自然地想到状态定义:$f[u][k][0/1][0/1]$表示以$u$为根的子树中,总共选择$k$个结点,其中除了$u$以外的所有结点均被监听到,$u$结点选或不选,$u$结点是否被覆盖的情况下,一共有多少种方案。

状态转移看似十分麻烦。每个结点$u$都有许多子结点,很难统计出每个子结点的所有情况(似乎在组合数学的范畴)。但是我们可以用十分巧妙的树形背包来进行状态转移。树上背包的转移套路是:

$$
f[u][i+j]=combine(f[u][i],f[v][j])
$$

相当于每递归访问完一个子结点,就把子节点上的状态与当前已经处理的状态一一配对,保证不重不漏且兼顾效率。具体的转移方程为:

$$
f[u][i+j][0][0]=\sum f[u][i][0][0]*f[v][j][0][1]
$$

$$
f[u][i+j][1][0]=\sum f[u][i][1][0]*(f[v][j][0][0]+f[v][j][0][1])
$$

$$
f[u][i+j][0][1]=\sum (f[u][i][0][1]*(f[v][j][0][1]+f[v][j][1][1])+f[u][i][0][0]*f[v][j][1][1]
$$

$$
f[u][i+j][1][1]=\sum (f[u][i][1][0]*(f[v][j][1][0]+f[v][j][1][1])+f[u][i][1][1]*(f[v][j][0][0]+f[v][j][0][1]+f[v][j][1][0]+f[v][j][1][1]))
$$

具体实现时还应注意:因为阶段(即扫描子结点个数)的划分,在每次转移前都要先记录原始的$u$结点上的数据,否则会导致混乱。

背包类树形 DP

写的不好!计划重写一篇。

树形背包博大精深!

绝对不咕!

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×