题目来源:http://www.lintcode.com/zh-cn/problem/house-robber/
题目描述
假设你是一个专业的窃贼,准备沿着一条街打劫房屋。每个房子都存放着特定金额的钱。你面临的唯一约束条件是:相邻的房子装着相互联系的防盗系统,且 当相邻的两个房子同一天被打劫时,该系统会自动报警。
给定一个非负整数列表,表示每个房子中存放的钱, 算一算,如果今晚去打劫,在不触动报警装置的情况下, 你最多可以得到多少钱。
翻译(转化)
在数组中取出一个或多个不相邻数,使其和最大,即找到max(不相邻元素组成的子数组)
解决方法 = 动态规划
举例,求a = [1,8,5,6,9]
中不相邻元素组成的子数组的最大和
a[0~index] | max(不相邻元素组成的子数组) |
---|---|
a[0] | m0 = 1 |
a[0~1] = a[0,1] | m1 = max(m0 , a[1]) = 8 |
a[0~2] = a[0,1,2] | m2 = max( m0 + a[2] , m1) = max(1 + 5, 8) = 8 |
a[0~3] = a[0,1,2,3] | m3 = max( m0 + a[3] , m1 + a[3] , m2) = max(m1 + a[3] , m2) = max(14,8) = 14 |
a[0~4] = a[0,1,2,3,4] | m4 = max( m0 + a[4] , m1 + a[4] , m2 + a[4] , m3) = max(m2 + a[4] , m3) = max(8 + 9 ,14) = 17 |
疑问1,m3 = max( m0 + a[3] , m1 + a[3] , m2) ,为什么只有m2不需要加上a[3]?
m2对应的数组是a[0~2],
- 假设a[0~2]的最大不相邻子数组a2用到了最后一个元素,那么a[0~3]的最大不相邻的子数组肯定不是a2+a[3];
- 假设a[0~2]的最大不相邻子数组a2没有用到最后一个元素,那么a[0~2]等于a[0~1]的最大不相邻子数组;
所以m2不需要加a[3]。
同理可得:a[0~n] = max(a[0] + a[n] , a[0~1] + a[n] ….a[0~n-2] + a[n] , a[0~n - 1])
疑问2,以上等式转换是怎么来的?
a[0~3] = max( m0 + a[3] , m1 + a[3] , m2)
因为m1 = max(m0, a[1]);
所以m1 + a[3] >= m0 + a[3];
所以a[0~3] = max(m1 + a[3] , m2) = max(8 + 6, 8) = 14;
a[0~4] = max( m0 + a[4] , m1 + a[4] , m2 + a[4] , m3);
因为m1 = max(m0, a[1]),m2 = max( m0 + a[2] , m1);
所以m2 >= m1 >= m0;
所以a[0~4] = max(m2 + a[4] , m3);
由以上可以得出状态转移方程:dp[n] = max(dp[n - 2] + a[n] , dp[n - 1])
代码
long long houseRobber(vector<int> nums) {
int size = nums.size();
if (size == 0) {
return 0;
}
if (size == 1) {
return nums[0];
}
if (size == 2) {
return nums[0] > nums[1] ? nums[0]:nums[1];
}
long long n1 = nums[0];
long long n2 = n1 > nums[1]?n1:nums[1];
long long n3, n4;
for (int i = 2; i < size; i++) {
n3 = n1 + nums[i];
n4 = n3 > n2 ? n3:n2;
n1 = n2;
n2 = n4;
}
return n1 > n2 ? n1:n2;
}
请尊重作者的劳动,转载请注明作者及原文地址(http://blog.csdn.net/lis_12/article/details/55187884).
如果觉得本文对您有帮助,请点击‘顶’支持一下,您的支持是我写作最大的动力,谢谢。