LeetCode198 House Robber(打家劫舍)

题目

You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security system connected and it will automatically contact the police if two adjacent houses were broken into on the same night.

Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police.

Example 1:

Input: [1,2,3,1]
Output: 4
Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3).
             Total amount you can rob = 1 + 3 = 4.

Example 2:

Input: [2,7,9,3,1]
Output: 12
Explanation: Rob house 1 (money = 2), rob house 3 (money = 9) and rob house 5 (money = 1).
             Total amount you can rob = 2 + 9 + 1 = 12.

翻译

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警

给定一个代表每个房屋存放金额的非负整数数组,计算你在不触动警报装置的情况下,能够偷窃到的最高金额。

解题思路

这一题是动态规划问题, 所以首先应该

把问题划分为子问题

分析:

求抢完后的最大金额–>抢到最后一家之后抢到的最大金额,

强盗可能把每一家都当做最后一家抢的店, 所以建立一个数组rob_house_money ,每一项表示当把这一家当做最后抢的店,抢完后获得的最大的钱
rob_house_money [ i ]表示把i当做最后一家要抢的店,抢完后的最大金额
则 最优解可以表示为rob_house_money的最大值

那么rob_house_money的每一个值怎么求呢?因为题目给了要求不能抢相邻的店*, 所以递归式子表示为

for (int j = 0; j < i - 1; j++) {
    rob_house_money[i] = max(rob_house_money[i], nums[i] + rob_house_money[j]);    
}

前面抢了j店, 然后加上本身店的钱 就是 rob_house_money[i]的值,而且我们都是保留最大的金额, 所以 循环每一个符合条件的店,把最大值赋值给rob_house_money[i]

class Solution {
public:
    int rob(vector<int>& nums) {
        //异常输出处理
        if (nums.size() == 0) {
            return 0;
        }
        //初始化rob_house_money 
        vector<int> rob_house_money = nums;

        for (int i = 2; i < nums.size(); i++){
            //从第三个房子开始计算, 前面两个房子的值就是本身
            for (int j = 0; j < i - 1; j++) {
                //i - 1 就略过了相邻的点(前一个店)
                rob_house_money[i] = max(rob_house_money[i], nums[i] + rob_house_money[j]);    
            }

        }
        //返回数组的最大值
        return *max_element(rob_house_money.begin(), rob_house_money.end());

    }
};

代码优化:

我们发现其实把前面的当做最后一家抢劫的店其实是没有必要的,我们发现rob_house_money[i]的值可以表示为
rob_house_money[i] = max(rob_house_money[i - 1], rob_house_money[i-2] +nums[i])

class Solution {
public:
    int rob(vector<int>& nums) {

        if (nums.size() == 0) {
            return 0;
        }

        vector<int> rob_house_money = nums;
        //第二个房子需要取 第一个房子和第二个房子的最大值这样才能保持rob_house_money[i-2]是最优的
        rob_house_money[1] = max(rob_house_money [0], rob_house_money [1]); 
        for (int i = 2; i < nums.size(); i++){
            rob_house_money[i] = max(rob_house_money[i - 1], rob_house_money[i-2] +nums[i]) ;
        }

        return  *max_element(rob_house_money.begin(), rob_house_money.end());

    }
};
posted @ 2018-09-10 11:40  qq874455953  阅读(166)  评论(0编辑  收藏  举报