【问题标题】:Leetcode House robberLeetcode 强盗
【发布时间】:2017-01-25 07:01:50
【问题描述】:

我在 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];
   }

但我就是无法理解这个逻辑。请帮助我了解逻辑以及如何解决此类问题?

【问题讨论】:

    标签: algorithm dynamic-programming


    【解决方案1】:

    基本上答案是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,因此选择f(n-2) + arr[n]。但是,如果您不选择7,则您最大的f(2) 将与f(1) 相同,即f(n-1)

    当数组为[9,1,7,9]时,需要去掉1和7,选择9、9。f(n) = max( f(n-1), f(n-2)+arr[n] )方程满足这种情况。

    【讨论】:

      【解决方案2】:

      假设我将金额存储在house[k]的第k宫。

      假设现在我将可以从前 k 个房屋(并且仅限前 k 个)中抢劫的最大金额存储在 max[k]

      现在考虑不考虑房子,所以max[0]=0

      现在只考虑第一所房子,max[1]=房子 1 的金额

      现在考虑前 2 个房子,

      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个房子可以抢劫的最大数量。

      只有当您之前进行过一些练习和熟悉时,DP 问题才会引起您的注意,这总是有帮助的。

      【讨论】:

        【解决方案3】:

        看看这个简单的递归代码。乍一看,很难想象在 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))
        

        如果您想提高效率,这也很容易记忆。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-07-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-01-03
          • 2018-09-12
          • 2019-06-13
          • 1970-01-01
          相关资源
          最近更新 更多