灵神基础算法精讲-25-学习笔记
树形DP
968.监控二叉树
给定一个二叉树,在树的节点上安装摄像头。
节点上的每个摄像头都可以监视其父对象、自身及其直接子对象。
计算监控树的所有节点所需的最小摄像头数量。
首先分析根节点装不装摄像头,比如根节点不装摄像头,那么它至少有一个儿子要装摄像头。
除了根节点以外,根据选或不选的思想,有以下三种方式:
- 选,在这个节点装摄像头
- 不选,在它的父节点装摄像头
- 不选,在它的左/右儿子装摄像头
分类讨论
- 对于蓝色节点来说,它的儿子装不装摄像头都可以,左右儿子可以是任意颜色,所以: 蓝色 = min(左蓝,左黄,左红) + min(右蓝,右黄,右红) + 1
- 对于黄色节点来说,它的儿子不可能是黄色节点,因为黄色节点的定义就是父节点要安装摄像头,所以: 黄色 = min(左蓝,左红) + min(右蓝,右红)
- 对于红色节点来说,它的儿子同样不可能是黄色节点,且它的儿子至少有一个是蓝色,所以: 红色 = min(左蓝+右红,左红+右蓝,左蓝+右蓝)
- 对于根节点来说,它没有父节点,所以根节点不可能是黄色,所以: 最终答案 = min(根节点为蓝色,根节点为红色)
递归边界
将空节点作为递归边界。空节点不能装摄像头,若递归到空节点为蓝色,则返回无穷大,表示不合法;空节点不需要被监控,若递归到空节点为黄色或红色,则返回0
1 |
|
变形1
在节点x安装摄像头,需要花费cost[x],求监控所有节点的最小花费
原问题相当于每个节点的花费都是1,求解该问题只需要将原代码中的+1改为+cost[node]
变形2
化简求解红色节点的式子,红色节点至少要有一个蓝色的儿子,若去掉这个约束,则求解红色节点等价于求解黄色节点,即min(蓝1,红1) + min(蓝2,红2),在此基础上加上至少有一个蓝色节点这一约束即可。当所有红色儿子的值小于蓝色儿子的值时,所有儿子均为红色,可以把其中一个红色儿子改成蓝色,就是改一个蓝色减红色最小的儿子,若蓝色本来就是小于等于红色,则无需修改,因此,在计算黄色公式的基础上,增加一个蓝色减红色的最小值,如果这个最小值是负数,说明至少有一个蓝色儿子小于红色,所以最后和0取最大值。
红色的计算公式更新为: 红色 = 黄色 + max(0, min(蓝1-红1,蓝2-红2))
由此可以看出红色一定大于等于黄色,所以蓝色的计算公式可以去掉带有红色和黄色取最小值的项。
灵神基础算法精讲-25-学习笔记
https://cosmoliu2002.github.io/posts/binary-tree-cameras/