打家劫舍II

dp问题描述

打家劫舍2
这个题和打家劫舍一的最大区别就在于,他的数组是一个环形数组,首尾是相连的,因此如果我们不允许小偷去偷两个相邻的房屋,那么第一个和最后一个房屋,也是不能同时偷的!
因此这个题的解题关键就在于对第一个房子偷不偷进行分类讨论。

  • 假如说我偷了第一个房子,那么我最后一个房子以及第二个房子就不能偷了。剩余的房子随便偷(按照打家劫舍1的模型计算出从第三个房子到倒数第二个房子中偷到的最高金额)
  • 如果我没有投第一个话,那么其余的房子随便投(按照打家劫舍1的模型计算出从第二个房子到最后一个房子中偷到的最高金额)

在这里插入图片描述

确定本题的状态表示

dp[i] 表示:从dp[0]这个房子到dp[i]这个房子偷到的最高金额(从dp[0~i]这一子序列中偷到的最高金额)

我们根据最后一个房子偷或者不偷继续细化:

{ f [ i ] 表示:选择到 i 位置的时候,选择 n u m s [ i ] ,此时子序列中偷到的最高金额 g [ i ] 表示:选择到 i 位置的时候,不选 n u m s [ i ] ,此时子序列中偷到的最高金额 \begin{cases} f[i] 表示:选择到 i 位置的时候,选择nums[i] ,此时子序列中偷到的最高金额 \\ g[i] 表示:选择到 i 位置的时候,不选nums[i] ,此时子序列中偷到的最高金额 \end{cases} {f[i]表示:选择到i位置的时候,选择nums[i],此时子序列中偷到的最高金额g[i]表示:选择到i位置的时候,不选nums[i],此时子序列中偷到的最高金额

确定本题的状态转移方程

依然是
f[i]=g[i-1]+nums[1]
g[i]=max(f[i-1],g[i-1])

填表求值

根据初始条件和状态转移方程,确定填表顺序,进而逐步填满dp表,最终返回题目要的结果

代码实现

class Solution {
public:
    int rob1(vector<int>& nums) {
        int n=nums.size();
        if(n==0) return 0;
        vector<int> f(n),g(n);
        f[0]=nums[0];g[0]=0;
        for(int i=1;i<n;i++){
            f[i]=g[i-1]+nums[i];
            g[i]=max(f[i-1],g[i-1]);
        }
        return max(g[n-1],f[n-1]);
    }
    int rob(vector<int>& nums) {
        if(nums.size()==1) return nums[0];
        if(nums.size()==2) return max(nums[0],nums[1]);
        vector<int> nums1(nums.begin()+1,nums.end());
        vector<int> nums2(nums.begin()+2,nums.end()-1);

        return max(rob1(nums1),rob1(nums2)+nums[0]);

    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值