题目
思路
首先我们来解读一下题目:我们将题目简介化就是:要求数组[o,n]范围内的元素最大和,且任意两个元素之间不能相邻
首先讲一下大体思路吧:
- 设置一个dp表,dp[i]表示[0,i]范围内所能获取的最大利益
- 状态转移方程可得:dp[i]=max(dp[i-1],dp[i-2]+nums[i])
其实这道题的思路也是挺简单的,就是设置一个dp表,但是一开始我是不怎么理解这个状态转移方程的。那在这里说一下我的理解:
首先为什么这个状态转移方程是这样的?
我们先回顾一下dp[i]表示的意义:dp[i]表示的是数组范围[0,i]所能获取的最大利益,那么dp[i]为什么等于dp[i-1]和dp[i-2]+nums[i]之中的最大值呢?一开始我的疑问是:第i-1个房屋一定要偷吗从片面的状态转移方程来看好像要传达的就是这个意思。实际上不是这么理解的,我们一定要记住的是:dp[i]所表示的含义是[0,i]范围内的获取的最大利益,如果第i-1个房屋没有偷,那么此时dp[i-1]就等于dp[i-2],表示第i-1个并不属于要偷的目标,那么在这此刻,小偷所能获取的最大利益就等于范围内[0,i-2]所能获得的最大利益(这个就体现了动态规划中的子问题重叠问题:一个状态可能会在多个阶段中被重复使用)
所以我们再来重新解读一下这个状态转移方程:该方程表示,在第i个房子,该房子有两种选择:偷或者不偷,如果要偷的话,那么此时在该决策下所能获取的最大利益就为dp[i-2]+nums[i],dp[i-2]就表示范围[0,i-2]所能获取的最大利益;如果选择不偷,那么在这个决策下所能获取的最大利益就为dp[i-1],表示范围[i-1]所能获取的最大利益,然后在这两种决策下选择最优的哪一个,即状态转移方程
所以相关代码如下:
class Solution {
public:
int rob(vector<int>& nums) {
int size = nums.size();
int pre = 0;
int cur = 0;
for (int i = 0; i < size; i++) {
int temp = cur;
cur = max(pre + nums[i], cur);
pre = temp;
}
return cur;
}
};
补充:一般情况下,如果状态转移方程中是关于dp[i]和dp[i-1],那么我们只需要设置一个变量,如果状态转移方程中是dp[i]和dp[i-1],dp[i-2]的关系,那么就设置两个变量来表示