Description
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.
分析
设d(i)表示抢到第i家时的最大总金额(包括抢了第i家)。那么可以写出下面的状态转移方程:
d(i)=nums(i)+max(d(i-2), d(i-3))
因为不能连续地抢,所以不考虑d(i-1);那么可以从i-2家或i-3家抢过来。之所以不考虑d(i-4)或更前面的d值的原因是d(i-2)必定大于d(i-4),从之前的递推可以很明显得出这个结论;但是d(i-2)和d(i-3)的大小无法确定,需要进行比较;以此类推,只需要比较d(i-2)和d(i-3)即可。
计算完所有d值后,最后两家对应的较大d值就是问题的解。
代码如下:
class Solution {
public:
int rob(vector<int>& nums) {
int size = nums.size();
if (size == 0)
return 0;
if (size == 1)
return nums[0];
if (size == 2)
return max(nums[0], nums[1]);
if (size == 3)
return max(nums[1], nums[0] + nums[2]);
int *d = new int[size];
d[0] = nums[0];
d[1] = nums[1];
d[2] = nums[0] + nums[2];
for (int i = 3; i < size; i++)
d[i] = nums[i] + max(d[i - 2], d[i - 3]);
return max(d[size - 1], d[size - 2]);
}
};
上面的第一思路感觉比较复杂,还有一种更简单的思路:设d(i)是可以从前i家抢到的最大金额,这意味着第i家可能被抢了,也可能没被抢。
如果第i家没被抢,很明显d(i)=d(i-1)。
如果第i家被抢了,说明第i-1家没有被抢,d(i-1)=d(i-2),那么d(i)=nums(i)+d(i-2),只需要加上到第i-2家能抢到的最大金额就行。
需要做的选择就是抢不抢第i家。
代码如下:
class Solution {
public:
int rob(vector<int>& nums) {
int size = nums.size();
if (size == 0)
return 0;
if (size == 1)
return nums[0];
if (size == 2)
return max(nums[0], nums[1]);
int *d = new int[size];
d[0] = nums[0];
d[1] = max(nums[0], nums[1]);
for (int i = 2; i < size; i++)
d[i] = max(d[i - 1], nums[i] + d[i - 2]);
return d[size - 1];
}
};