一些动态规划题解

小偷盗窃问题

  • 问题描述:

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有必定的现金,影响你偷窃的惟一制约因素就是相邻的房屋装有相互连通的防盗系统,若是两间相邻的房屋在同一夜被小偷闯入,系统会自动报警。数组

给定一个表明每一个房屋存放金额的非负整数数组,计算你在不触动警报装置的状况下,可以偷窃到的最高金额。ui

示例 1:this

输入: [1,2,3,1] 输出: 4 解释: 偷窃 1 号房屋 (金额 = 1) ,而后偷窃 3 号房屋 (金额 = 3)。 偷窃到的最高金额 = 1 + 3 = 4 。spa

示例 2:code

输入: [2,7,9,3,1] 输出: 12 解释: 偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。 偷窃到的最高金额 = 2 + 9 + 1 = 12 。io

  • 问题求解 题意简单说来就是不能偷相邻的两个房屋, 并且要尽可能偷得多. 这是典型的动态规划问题, 思路以下, 因为后面房间能偷到的最大钱数取决于前面房间能偷到的最大钱数, 因此能够从第一间房子向后看. 创建一个数组dp, 数组中的第n个元素保存前n间房屋总共能偷到的最大钱数:
  1. 若只有一间房子, 则只能偷这间, 则前1间房屋能偷到的最大金额一已知, 保存下来;
  2. 如有两间, 则偷其中最多的, 则前两间房屋能偷到的最大金额已知, 保存下来;
  3. 如有3间, 则分为两种状况, 1)偷房屋 1和3; 2) 只偷房屋2. 比较这两种哪一种获益大. 这能够抽象成两个子问题, 决定这两个子问题的关键是第三间房子偷与否. 分别把偷(子问题1)和不偷(子问题2) 的结果计算出来, 选出最大就是了. 如今, 前三间能偷到的最大金额已知, 保存下来, 以供偷第四、5...N 间房子时参考.
  4. 如有4间, 则又是两种状况: 1)偷4不偷3; 2)不偷4. 这两种状况只和前三间房屋偷到的金额(dp[3])和前两间房屋偷到的金额(dp[2])的结果有关,把这两种状况下的金额计算出来, 选择最大的就能够了, 即 max(房屋4的钱+dp[2], dp[3]);
  5. 由此可得, 第n间房屋偷仍是不偷只要考虑 dp 数组中的dp[n-1]和dp[n-2]+当前可得的金额这两个因素就能够了.

因此状态方程为:max(dp[n-2] + thisValue, dp[n-1]), 代码为:function

var rob = function(nums) {
    // 判断异常
    if(!nums || nums.length === 0){ 
        return 0;
    }
    // 边界条件
    if(nums.length < 3){
        return Math.max(...nums);
    }
    
    // 状态方程 dp(i) = max( dp(i-1) , dp(2) + arr[i])
    let dp = [];
    dp[0] = nums[0];
    dp[1] = Math.max(nums[0],nums[1]);
    
    for(let i = 2; i < nums.length; i++){
        dp[i] = Math.max(dp[i-2] + nums[i], dp[i-1]);
    }
    
    return dp[dp.length-1];
};
复制代码

待续...class

相关文章
相关标签/搜索