题目链接:https://leetcode.com/problems/house-robber/
Runtimes:3ms
1、问题
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.
2、分析
大意就是说,有一排房子等着你偷,但是有个条件是相邻的两个房子不能同时偷,否则会自动报警。问题来了,怎么偷才能够让你获得最大的收益。
一拍脑袋想到要用动态规划(我会告诉你是看tip才知道的么?),那么要如何用呢?动态规划的一般思想是用空间换时间,那么就开一个数组r[],保留偷第i套房子的最大收益,那么你偷第i套房子的最大收益就是:r[i] = num[i] + max{r[j]}(0 < j < i - 1),因为隔壁第i+1套房子你是不能偷的。
举个栗子:
比如有以下房子等着你偷,数字代表现金的数量,请问你要怎么偷才收获最大。
0 1 2 3 4 5 6 7 8 1 7 8 5 6 2 1 3 10 思路:
(1)偷第0套房子的时候,你前面没房子,所以r[0] = 1
(2)偷第1套房子的时候,你隔壁房子不能偷,隔壁房子前面又没房子,因此r[1] = 7
(3)偷第2套房子的时候,你隔壁房子的前面一套房子最大值为1,因此偷第0、2套房子让你获得最大值,因此r[2] = 9
(4)偷第3套房子的时候,你隔壁房子的前面有两套房子,如果偷第0、3套,r[3] = 6,偷第1、3套,r[3] = 12,因此你肯定选择最大的,即r[3] = 5 + max{r[0], r[1]}
……以此类推,得到r[],取得r[]最大值即可。
3、小结
一些细节问题老是没有处理,比如num为0的情况,比如0 、1的情况没有独自处理等等。一定要自己设置一下测试样例以及可能出现的情况。
4、实现
class Solution {
public:
int rob(vector<int> &num) {
if(num.empty())
return 0;
int *r = new int[num.size()];
int max = INT_MIN;
for(int i = 0; i < num.size(); ++i)
{
r[i] = 0;
}
for(int i = 0; i < num.size(); ++i)
{
if(i == 0 || i == 1)
{
r[i] = num[i];
}else{
for (int j = 0; j < i - 1; ++j)
{
if(r[i] < r[j] + num[i])
{
r[i] = r[j] + num[i];
}
}
}
if(r[i] > max)
max = r[i];
}
delete r;
return max;
}
};
5、反思
一篇讲解动态规划的文章,不错,推荐一下,即使看完你离专家还远着呢,赶紧coding!
文章链接:http://www.hawstein.com/posts/dp-novice-to-advanced.html