一些動態規劃題解

小偷盜竊問題

  • 問題描述:

你是一個專業的小偷,計劃偷竊沿街的房屋。每間房內都藏有必定的現金,影響你偷竊的惟一制約因素就是相鄰的房屋裝有相互連通的防盜系統,若是兩間相鄰的房屋在同一夜被小偷闖入,系統會自動報警。數組

給定一個表明每一個房屋存放金額的非負整數數組,計算你在不觸動警報裝置的狀況下,可以偷竊到的最高金額。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

相關文章
相關標籤/搜索