基于经典“没有上司的舞会”,展示自叶子节点向根节点自底向上波流汇集的状态转移过程
树型动态规划是在树状结构上进行的 DP。由于树具有天然的递归子结构,我们通常采用 后序遍历 (Post-order DFS):先深度搜索所有子节点,在回溯归纳时再将子树的信息汇集给父节点进行决策。
每个节点代表一个职员,其有特定的快乐值 fun[u]。任何职员都不能与其直接上司同时参加舞会。求舞会最大快乐值之和。
我们用 f[u][1] 表示职员 $u$ 参加舞会时,$u$ 及其子树能获得的最大快乐;f[u][0] 表示 $u$ 不参加舞会时的最大快乐:
void dfs(int u) {
f[u][0] = 0;
f[u][1] = fun[u]; // 亲自参会初始快乐
for (int v : child[u]) {
dfs(v); // 递归先求解子树
// 状态转移归纳
f[u][0] += max(f[v][0], f[v][1]); // 放弃上司,下属选最优
f[u][1] += f[v][0]; // 亲自出席,下属必须缺席
}
}