[LintCode 535.] 打劫房屋 III

LintCode 535. 打劫房屋 III

题目描述

在上次打劫完一条街道之后和一圈房屋之后,窃贼又发现了一个新的可以打劫的地方,但这次所有的房子组成的区域比较奇怪,聪明的窃贼考察地形之后,发现这次的地形是一颗二叉树。与前两次偷窃相似的是每个房子都存放着特定金额的钱。你面临的唯一约束条件是:相邻的房子装着相互联系的防盗系统,且当相邻的两个房子同一天被打劫时,该系统会自动报警。

算一算,如果今晚去打劫,你最多可以得到多少钱,当然在不触动报警装置的情况下。

样例

样例1

输入: {3,2,3,#,3,#,1}
输出: 7
解释:
最多能偷 3 + 3 + 1 = 7.

  3
 / \
2   3
 \   \ 
  3   1

样例2

输入: {3,4,5,1,3,#,1}
输出: 9
解释:
最多能偷 4 + 5 = 9.

    3
   / \
  4   5
 / \   \ 
1   3   1

解题思路

这题是House Robber和House Robber II的扩展,只不过这次地形由直线和圈变成了二叉树。
解题思路与 [LintCode 614.] 二叉树的最长连续子序列 II 类似:
使用记录每一个结点的状态,递归计算得出答案。
这里对于每一个结点都有两状态,被抢劫,或者不被抢劫。需要的状态为当前子树上抢劫的最大收益,对于一个结点:

  • 如果被抢劫,那么收益就是当前结点的收益 + 两棵子树上不抢劫各自根结点的收益;
  • 如果不抢劫,那么收益就是两棵子树上的最大收益之和 —— 每棵子树都可以抢根节点或者不抢根节点,取收益最大的操作即可。
    最终我们需要的就是从根节点的两种操作中的收益中,取最大收益即可。

补充测试样例

{1, 2, 3, 5, 4}

    1
   / \
  2   3
 / \ 
5   4

最多能偷 5 + 4 + 3 = 12。

参考代码

/**
 * Definition of TreeNode:
 * class TreeNode {
 * public:
 *     int val;
 *     TreeNode *left, *right;
 *     TreeNode(int val) {
 *         this->val = val;
 *         this->left = this->right = NULL;
 *     }
 * }
 */

struct Res {
    int rob;
    int skip;
};

class Solution {
public:
    /**
     * @param root: The root of binary tree.
     * @return: The maximum amount of money you can rob tonight
     */
    int houseRobber3(TreeNode * root) {
        // write your code here
        Res res = rob3(root);
        return max(res.rob, res.skip);
    }
    static Res rob3(TreeNode* r) {
        if (r == NULL) return {0, 0};

        Res res1 = rob3(r->left);
        Res res2 = rob3(r->right);
        int rob = r->val + res1.skip + res2.skip;
        int skip = max(res1.rob, res1.skip) + max(res2.rob, res2.skip);
        return {rob, skip};
    }
};
posted @ 2021-01-12 13:23  与MPI做斗争  阅读(72)  评论(0编辑  收藏  举报