地址:https://leetcode-cn.com/problems/binary-tree-cameras/
思路:贪心/树状dp
1.贪心:对于树来说,监控父节点一定不监控子节点覆盖的点多,因此只要从叶子节点处贪心,同时记录当前节点的状态即可,节点的有三种状态:0-节点未被覆盖、1-节点被覆盖但不是监控点、2-节点为覆盖点
2.树状dp:节点同样是这三种状态,dp[i][j]为子树 i 为 j 状态时被覆盖所需要监控节点的最小数量
再对父节点的左右节点是否存在分类讨论即可
Code 1:
//贪心
class Solution {
private:
int ans;
public:
int minCameraCover(TreeNode* root){
int ss=Find(root);
if(!ss) ++ans;
return ans;
}
int Find(TreeNode* root){
if(root==NULL){
return 1;
}
int s1=Find(root->left);
int s2=Find(root->right);
int res=0;
if(!s1||!s2){
++ans;
res=2;
}else if(s1==1&&s2==1){
res=0;
}else{
res=1;
}
return res;
}
};
Code 2:
//树状DP
class Solution {
public:
int tmp;
int dp[1005][3];
int minCameraCover(TreeNode* root){
if(root==NULL){
return 0;
}
root->val=++tmp;
minCameraCover(root->left);
minCameraCover(root->right);
int l,r,u=root->val;
if(root->left!=NULL&&root->right!=NULL){
l=root->left->val;
r=root->right->val;
dp[u][0]=dp[l][1]+dp[r][1];
dp[u][1]=min(dp[l][2]+dp[r][1],min(dp[l][1]+dp[r][2],dp[l][2]+dp[r][2]));
dp[u][2]=dp[l][0]+dp[r][0];
for(int i=0;i<3;++i)
for(int j=0;j<3;++j)
dp[u][2]=min(dp[u][2],dp[l][i]+dp[r][j]);
dp[u][2]+=1;
}else if(root->left!=NULL){
l=root->left->val;
dp[u][0]=dp[l][1];
dp[u][1]=dp[l][2];
dp[u][2]=min(dp[l][0],min(dp[l][1],dp[l][2]))+1;
}else if(root->right!=NULL){
r=root->right->val;
dp[u][0]=dp[r][1];
dp[u][1]=dp[r][2];
dp[u][2]=min(dp[r][0],min(dp[r][1],dp[r][2]))+1;
}else{
dp[u][1]=dp[u][2]=1;
}
return min(dp[u][1],dp[u][2]);
}
};