Skip to content

Latest commit

 

History

History

968.Binary-Tree-Cameras

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 

968.Binary-Tree-Cameras

本题粗看有点像house robber系列,考虑是否可以用DP来解,似乎应该设计三个状态:本身没有被cover(0),本身有camera(1),本身没camera但是被邻近的camera给cover了(2)。基本的思路应该是,按照从上往下的顺序,后续节点的状态取决于前面的(若干个)节点状态。但是问题在于,依照从上往下的顺序的话,每个节点只能受父节点或者更高层的节点影响,显然是不合适的,因为它应该还应该受平行的兄弟节点的影响,而这个在线性的DP遍历中没法实现(因为你没法保证在考察这个node之前,它的兄弟node已经被更新过了)。

于是我们反向考虑,如果从下往上走会怎么样?这样,每个节点的状态可以取决于它的两个子节点。这个方案似乎有戏。为什么呢?假设我们从下往上依次更新,考察node时它的两个子节点的状态是已知的:

1.如果当前node的两个子节点只要有一个状态是0,那么该node必须设置为状态1,以保证两个子节点都被cover到。相应result++.

2.如果当前node的两个子节点都是状态2,那么按照从简的原则,当前node就可以不必安排camera,故状态可以设置为0。状态是0了没有被cover怎么办?不用担心,靠后续node的父节点来兜着就行,当前不用操心。

3.其他情况下,当前node都没有必要设置camera,并且当前node必然已经被某个子节点给cover了,所以我们设置node状态为2.

有了以上的传递关系,我们再考虑边界条件。边界条件就是叶子节点(最底层)。直觉告诉我们,所有的叶子节点没有必要设置camera,只要把camera放在它的父节点即可,这样肯定不亏(父节点装一个camera可以管两个子节点)。事实上,这个贪心法的思想(将最底层节点设置状态为2)是整个递归传递(从下往上更新)的根基。因此只有double check这个贪心的思想是对的,这个算法才是可行的。

最后需要注意的是,如果根节点最终设置状态为0了(此时程序结束),那么我还需要额外再在root上加一个camera以覆盖root。