我在leet代码上尝试House Robber问题(dp问题)。 来自用户GYX的这个解决方案看起来简单而优雅。
int rob(vector<int>& num) {
int n = num.size();
if (n==0) return 0;
vector<int> result(n+1,0);
result[1] = num[0];
for (int i=2;i<=n;i++){
result[i] = max(result[i-1],result[i-2]+num[i-1]);
}
return result[n];
}
但我无法理解逻辑。请帮助我解决逻辑,以及如何处理这样的问题?
答案 0 :(得分:6)
基本上答案是f(n) = max( f(n-1), f(n-2) + arr[n] )
,你问为什么。
假设这个数组arr = [9,1,7,9]
和f(n)
是函数。
当数组仅为[9]
时,您的最高f(0)
将为arr[0]
。
当数组为[9,1]
时,您的最高f(1)
为max(arr[0], arr[1])
。
当数组为[9,1,7]
时,如果您选择7
,则无法选择1
{{1} }}。但是,如果您未选择f(n-2) + arr[n]
,则最高7
将与f(2)
f(1)
相同。
当数组为f(n-1)
时,您需要同时删除1&amp; 7并选择9,9。[9,1,7,9]
等式满足这种情况。
答案 1 :(得分:2)
假设我将金额存储在house[k]
中的第k个房子中。
假设现在我存储了max[k]
中从前k个房屋(仅限第一个k)中掠夺的最大金额。
现在考虑没有房子,所以max[0]=0
现在只考虑第一宫,max[1]
=房屋1中的金额
现在考虑前两个房子,
max[2]
= {或max[1]
(暗示我们选择抢劫房屋1)或(房屋2中的金额+我抢劫的最高金额,直到房子位于我当前房屋前2个地方)} = {max(max[1],house[2]+max[0])}
同样对于前3个房屋,max[3]=max(max[2],house[3]+max[1])
观察这一趋势,可以制定max[k]=max(max[k-1],house[k]+max[k-2])
。这个值计算到最后没有房子的时候,我们得到了这些前n个房子可以抢劫的最高金额。
答案 2 :(得分:0)
看看这个简单的递归代码。乍看之下,很难解决DP中解决的问题。您应该始终从性能低下的递归代码开始努力。这是代码的不同版本:
p = [0, 1, 2, 3, 1, 2, 3, 1, 2, 5, 8, 2]
def R(i):
if i == 1 or i == 2:
return i
else:
return max(p[i] + R(i - 2), R(i - 1))
print(R(11))
如果您想提高效率,这也很容易记住。