leetcode198.打家劫舍,動態規劃

  1. 題目:
    你是一個專業的小偷,計劃偷竊沿街的房屋。每間房內都藏有一定的現金,影響你偷竊的唯一制約因素就是相鄰的房屋裝有相互連通的防盜系統,如果兩間相鄰的房屋在同一晚上被小偷闖入,系統會自動報警。
    給定一個代表每個房屋存放金額的非負整數數組,計算你在不觸動警報裝置的情況下,能夠偷竊到的最高金額。
  2. 示例:
    示例 1:

輸入: [1,2,3,1]
輸出: 4
解釋: 偷竊 1 號房屋 (金額 = 1) ,然後偷竊 3 號房屋 (金額 = 3)。
偷竊到的最高金額 = 1 + 3 = 4 。
示例 2:
輸入: [2,7,9,3,1]
輸出: 12
解釋: 偷竊 1 號房屋 (金額 = 2), 偷竊 3 號房屋 (金額 = 9),接着偷竊 5 號房屋 (金額 = 1)。
偷竊到的最高金額 = 2 + 9 + 1 = 12 。
3. 思路:
暴力解法:檢查所有房子的組合,對每一個組合,檢查是否有相鄰的房子,如果沒有,記錄其價值。找最大值。O((2^n)*n) 組合問題
在這裏插入圖片描述
注意其中對狀態的定義:
考慮偷取[x…n-1]範圍裏的房子(函數的定義)
根據對狀態的定義,決定狀態的轉移:
f(0)=max{v(0)+f{2},v(1)+f(3),v(2)+f(4),…,v(n-3)+f(n-1),v(n-2),v(n-1)} (狀態轉移方程)
4. 代碼:
遞歸求解會超時。

class Solution {
public:
    int rob(vector<int>& nums) {
        return tryRob(nums,0);
    }
private:
    //考慮搶劫nums[index,...nums.size()-1]這個範圍內的所有房子
    int tryRob(vector<int>& nums,int index){
        if(index>=nums.size())
            return 0;
        int res=0;
        for(int i=index;i<nums.size();i++)
            res=max(res,nums[i]+tryRob(nums,i+2));
        return res;
    }
};

記憶化搜索:

class Solution {
public:
    int rob(vector<int>& nums) {
        memo=vector<int>(nums.size(),-1);
        return tryRob(nums,0);
    }
private:
    //memo[i]考慮搶劫nums[i,...nums.size()-1]這個範圍內的所有房子能獲得的最大收益
    vector<int> memo;
    int tryRob(vector<int>& nums,int index){
        if(index>=nums.size())
            return 0;
        if(memo[index]!=-1)
            return memo[index];
        int res=0;
        for(int i=index;i<nums.size();i++)
            res=max(res,nums[i]+tryRob(nums,i+2));
        memo[index]=res;
        return res;
    }
};

動態規劃

class Solution {
public:
    int rob(vector<int>& nums) {
        int n=nums.size();
        if(n==0) return 0;
        //dp[i]表示考慮搶劫nums[i...n-1]所能獲得的最大收益
        vector<int> dp(n,-1);
        dp[n-1]=nums[n-1];
        for(int i=n-2;i>=0;i--)
            //dp[i]計算
            for(int j=i;j<n;j++)
                dp[i]=max(dp[i],nums[j]+(j+2<n?dp[j+2]:0));
        return dp[0];
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章