【问题标题】:Intuition behind the base cases of this DP此 DP 基本案例背后的直觉
【发布时间】:2017-11-03 19:45:34
【问题描述】:

我正在尝试解决以下 DP 问题:

给定一个代表每所房子金额的非负整数列表,确定今晚你可以在不报警的情况下抢劫的最大金额。您不能抢劫相邻的房屋,因为这样做会引起警察的注意。

给出的解决方案之一是:

class Solution {
public:
    int rob(vector<int>& nums) {
        if(nums.empty())
            return 0;

        if(nums.size()==1)
            return nums[0];

        vector<int> dp(nums.size());
        dp[0] = nums[0];
        dp[1] = max(nums[0], nums[1]);

        for(int i=2; i<(int)nums.size(); i++) {
            dp[i] = max(dp[i-2]+nums[i], dp[i-1]);
        }

        return dp[nums.size()-1];
    }
};

有人可以指出dp[1]初始化背后的直觉:

dp[1] = max(nums[0], nums[1]);

我将它初始化为dp[1] = nums[1]。但是,它会在 [3,1,4,10] 之类的测试用例上中断。当我们将其初始化为max(nums[0], nums[1]); 时,我们不是有点 将输入数组更改为[3,3,4,10] 吗?它如何帮助我们找到最终(正确)的解决方案?

注意:问题来自here

编辑:指南是否建议在对此类问题的基本案例进行硬编码时考虑我们的主要 DP 公式?

【问题讨论】:

    标签: c++ dynamic-programming


    【解决方案1】:

    为了最大化你可以抢劫的钱,你必须从第一所房子或第二所房子开始抢劫。您不能同时抢劫它们,因为它们是相邻的,这不符合给定条件。

    你不能抢任何一个,因为你会错过一所房子,这将导致一个不是全局最大值的值。

    该初始化可以看作是“从房子 0 开始到房子 1(包括)你可以抢劫的最大数量”。您的初始化表明您可以从前两个房屋中抢劫的最大值仅为 1(不是 3,因为它必须是),这是错误的,导致错误的最大值。

    【讨论】:

    • 很好的解释,谢谢! :) 我会尽快接受你的回答。
    • 另外,我是否应该概括一下我们在生成基本案例时应该考虑递归公式?
    • 这是一种自下而上的 DP 方法 - 全局最大值是通过建立在基本情况下获得的。递归公式本身基于最后两个计算的最大值。您无法使用此公式生成基本情况,因为它使用的值不存在(根据公式,您需要dp[-2]dp[-1],这是无效的)。
    • 是的,我明白这一点。我在问如何生成基本案例;不是我们是否应该生成它们。我们是否应该生成的答案对我来说是显而易见的。我想知道如何生成它们。
    • 基本情况因 DP 问题而异,但是当您处理更多问题时,识别基本情况和递归公式会变得更容易。实践会告诉你很多DP问题是相似的,可以用类似的方法解决。
    猜你喜欢
    • 1970-01-01
    • 2022-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-11
    • 2021-12-12
    • 2019-04-14
    相关资源
    最近更新 更多