天天看点

leetcode打家劫舍:动态规划(三)

博客《leetcode——动态规划(一):最大子序和》已经结合题目把动态规划的思想原理大概讲了一下,那么这篇博客主要针对更多典型的动态规划的题目,来对动态规划思想的应用进行更进一步的探讨。《leetcode——动态规划(二):爬楼梯》讨论了一道非常简单的题,这篇博客又要讲leetcode上另一道非常简单的题目:打家劫舍。

打家劫舍

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

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

示例 1:

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

示例 2:

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

思路分析:

其实这道题和上一篇博客讲到的爬楼梯的思路非常相似,我们可以将所有的房子的可以偷窃的价值看成是一个序列,序列[a0,a1,a2,...,an-1,an]的最优结果可以看作是在序列[a0,a1,a2,...,an-1]的基础上得来的。因为不能让偷窃的房子相邻,那么i个房子的最优偷窃方案带来的总价值s(i)=max(s(i-1),s(i-2)+ai)其中i>2。这样这个问题还是转化成了迭代求解的问题,已知s(0)和s(1),s(i)可通过迭代求解。

代码如下:

class Solution {
public:
    int rob(vector<int>& nums) {
        if(nums.size()==0)return 0;
        if(nums.size()==1)return nums[0];
        int profit[nums.size()];
        profit[0]=nums[0];
        profit[1]=max(nums[0],nums[1]);
        for(int i=2;i<nums.size();i++){
            profit[i]=max(profit[i-2]+nums[i],profit[i-1]);
        }
        return profit[nums.size()-1];
    }
};