树形dp 打家劫舍Ⅲ+监控二叉树

本文介绍如何使用树形动态规划解决两类二叉树问题:打家劫舍Ⅲ与监控二叉树。通过定义节点状态并利用递归方式传递子树信息,实现高效求解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

树形dp,递归调用栈把中间计算结果暂存了,子调用的结果交给父调用,它就销毁了,不需要记忆化。

解题时确定每个节点的所有状态,并从子调用逐个返回。

打家劫舍Ⅲ

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
struct Node {
    Node(){}
    Node(int rob, int norob):rob(rob),norob(norob){}
    int rob, norob;
};
class Solution {
public:
    Node dfs(TreeNode* rt) {
        if(rt == nullptr) {
            return Node(0, 0);
        }

        auto l = dfs(rt -> left);
        auto r = dfs(rt -> right);

        int rob = rt -> val + l.norob + r.norob;
        int norob = max(l.rob+r.rob, max(l.rob+r.norob, max(l.norob+r.rob, l.norob+r.norob)));

        return Node(rob, norob);
    }
    int rob(TreeNode* root) {
        auto res = dfs(root);
        return max(res.rob, res.norob);
    }
};

监控二叉树

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    struct Node {
        Node(){}
        Node(int withCam, int noCamWithFa, int noCamWithSon):withCam(withCam), noCamWithFa(noCamWithFa), noCamWithSon(noCamWithSon){}
        int withCam, noCamWithFa, noCamWithSon;
    };
    Node dfs(TreeNode* rt) {
        if(rt == nullptr) {
            return Node(0x3f3f3f, 0, 0);
        }

        Node l = dfs(rt -> left);
        Node r = dfs(rt -> right);
		
		// 确定不是最优的状态也不需要完全枚举
        int withCam = 1+min(l.withCam+r.withCam, 
        min(l.noCamWithFa+r.noCamWithFa, 
        min(l.withCam+r.noCamWithFa,
        l.noCamWithFa+r.withCam)));

        int noCamWithFa = min(l.noCamWithSon+r.noCamWithSon,
        min(l.withCam+r.noCamWithSon,
        min(l.withCam+r.withCam,
        r.withCam+l.noCamWithSon)
        ));

        int noCamWithSon = min(l.withCam+r.withCam,
        min(l.withCam+r.noCamWithSon, r.withCam+l.noCamWithSon)
        );

        return Node(withCam, noCamWithFa, noCamWithSon);
    }

    int minCameraCover(TreeNode* root) {
        auto res = dfs(root);
        return min(res.withCam, res.noCamWithSon);
    }
};
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值