leetcode---打家劫舍

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

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

输入: [1,2,3,1]
输出: 4
解释: 偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。
     偷窃到的最高金额 = 1 + 3 = 4

 

输入: [2,7,9,3,1]
输出: 12
解释: 偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。
     偷窃到的最高金额 = 2 + 9 + 1 = 12

 

我写的是动态规划标签,从而遇到这种题目,应该先想到怎么去弄出动态转移方程:

由于不能拿相邻的,因此我想的就是 f(n)=max(f(n-2),f(n-3))+val; 即当前最大值要么是从n - 2拿的,要么是从 n - 3 得到的;

class Solution {
public:
    int rob(vector& nums) {
        /*  想好转移方程 
            f(n)=max(f(n-2),f(n-3))+val;
            */
        int res = 0;
        int size = nums.size();
        int temp = 0;
        for(int i = 0; i < size; ++i)
        {
            if( i - 2 >= 0)
                temp = nums[i - 2];
            if( i - 3 >= 0)
                temp = max(temp, nums[i - 3]);
            nums[i] += temp;
            res = max(nums[i], res);
        }
        return res;
    }
}

其实,当前能拿到的最大值,要么是从n - 1得到的(在n处不拿),要么是从 n - 2 拿的再加上n处的val得到的

动态规划方程:dp[n] = MAX( dp[n-1], dp[n-2] + num )

 

 

拓展:

如果是环形数组(即最后一家和第一家相邻),若最后一个最大值是基于第一家拿的,那么就会报警;

这一题,我刚开始的思路是,如果最后一次拿的最大值是基于第一次拿的,我就拿n - 2 家的最大值,这样的逻辑并不对;

我应该想好情况:参考别人的思路

首先,首尾房间不能同时被抢,那么只可能有三种不同情况:要么都不被抢;要么第一间房子被抢最后一间不抢;要么最后一间房子被抢第一间不抢。

                                                                leetcode---打家劫舍_第1张图片

那就简单了啊,这三种情况,那种的结果最大,就是最终答案呗!不过,其实我们不需要比较三种情况,只要比较情况二和情况三就行了,因为这两种情况对于房子的选择余地比情况一大呀,房子里的钱数都是非负数,所以选择余地大,最优决策结果肯定不会小。

class Solution {
public:

    int rob2(vector nums, int lo, int hi)
    {
        if(lo == 1)
            nums[0] = 0;      //这么做是为了若是从1开始的话,那么n - 2 为0 的话,此时0处的值应该是0
        nums[lo + 1] = max(nums[lo], nums[lo + 1]);   //我的for循环是从2开始的,所以必须比较刚开始的两个值在1处的最大值
        for(int i = 2; i <= hi; ++i)
        {   
            nums[i] =max(nums[i - 2] + nums[i],nums[i - 1]);
        }
        return nums[hi];
    }

    int rob(vector& nums) {
        if(nums.empty())
            return 0;
        if(nums.size() == 1)
            return nums[0];
        if(nums.size() == 2)
            return max(nums[0],nums[1]);
        int size = nums.size();
        int res1 = rob2(nums, 0, size - 2);
        int res2 = rob2(nums, 1, size - 1);
        return (res1 > res2) ? res1 : res2; 
    }
};

 

你可能感兴趣的:(动态规划)