题目描述:(链接:力扣)
「力扣嘉年华」的中心广场放置了一个巨型的二叉树形状的装饰树。每个节点上均有一盏灯和三个开关。节点值为 0 表示灯处于「关闭」状态,节点值为 1 表示灯处于「开启」状态。每个节点上的三个开关各自功能如下:
开关 1:切换当前节点的灯的状态;
开关 2:切换 以当前节点为根 的子树中,所有节点上的灯的状态;
开关 3:切换 当前节点及其左右子节点(若存在的话) 上的灯的状态;
给定该装饰的初始状态 root
,请返回最少需要操作多少次开关,可以关闭所有节点的灯。
题目示例:
示例1:
输入:
root = [1,1,0,null,null,null,1]
输出:
2
示例2:
输入:
root = [1,1,1,1,null,null,1]
输出:
1
示例3:
输入:
root = [0,null,0]
输出:
0
题目提示:
1 <= 节点个数 <= 10^5
0 <= Node.val <= 1
题目分析:
树状dp,枚举所用的状态转移,一共四种状态,分别是1、根结点不亮,子树全部不亮;2、根结点亮,子树全部不亮;3、根结点亮,子树全部亮;4、根结点不亮,子树全部亮
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
// 一共四种转移状态
tuple<int,int,int,int> dfs(TreeNode* cur){
if(cur==NULL) return {0,0,0,0};
auto [la,lb,lc,ld]=dfs(cur->left);
auto [ra,rb,rc,rd]=dfs(cur->right);
int v=cur->val;
// 1、根结点不亮,子树全部不亮
int x = min({la + ra + (v ? 1 : 0), lb + rb + (v ? 1 : 2), lc + rc + (v ? 1 : 2), ld + rd + (v ? 3 : 2)});
// 2、根结点亮,子树全部不亮
int y = min({la + ra + (v ? 0 : 1), lb + rb + (v ? 2 : 1), lc + rc + (v ? 2 : 1), ld + rd + (v ? 2 : 3)});
// 3、根结点亮,子树全部亮
int z = min({la + ra + (v ? 2 : 1), lb + rb + (v ? 2 : 3), lc + rc + (v ? 0 : 1), ld + rd + (v ? 2 : 1)});
// 4、根结点不亮,子树全部亮
int k = min({la + ra + (v ? 1 : 2), lb + rb + (v ? 3 : 2), lc + rc + (v ? 1 : 0), ld + rd + (v ? 1 : 2)});
return {x,y,z,k};
}
int closeLampInTree(TreeNode* root) {
auto [x,y,z,k]=dfs(root);
return min({x,y+1,z+1,k+2});
}
};