• 213. 打家劫舍 II


    首先考虑最简单的情况。如果只有一间房屋,则偷窃该房屋,可以偷窃到最高总金额。如果只有两间房屋,则由于两间房屋相邻,不能同时偷窃,只能偷窃其中的一间房屋,因此选择其中金额较高的房屋进行偷窃,可以偷窃到最高总金额。

    注意到当房屋数量不超过两间时,最多只能偷窃一间房屋,因此不需要考虑首尾相连的问题。如果房屋数量大于两间,就必须考虑首尾相连的问题,第一间房屋和最后一间房屋不能同时偷窃。

    如何才能保证第一间房屋和最后一间房屋不同时偷窃呢?如果偷窃了第一间房屋,则不能偷窃最后一间房屋,因此偷窃房屋的范围是第一间房屋到最后第二间房屋;如果偷窃了最后一间房屋,则不能偷窃第一间房屋,因此偷窃房屋的范围是第二间房屋到最后一间房屋。

    假设数组( extit{nums})的长度为 nn。如果不偷窃最后一间房屋,则偷窃房屋的下标范围是 ([0, n-2]);如果不偷窃第一间房屋,则偷窃房屋的下标范围是([1, n-1])

    对于两段下标范围分别计算可以偷窃到的最高总金额,其中的最大值即为在 (n) 间房屋中可以偷窃到的最高总金额。

    假设偷窃房屋的下标范围是 ([ extit{start}, extit{end}]),用( extit{dp}[i])表示在下标范围([ extit{start},i])内可以偷窃到的最高总金额,那么就有如下的状态转移方程:

    [ extit{dp}[i] = max( extit{dp}[i-2]+ extit{nums}[i], extit{dp}[i-1]) ]

    边界条件为:

    [egin{cases} extit{dp}[ extit{start}] = extit{nums}[ extit{start}] & 只有一间房屋,则偷窃该房屋 \ extit{dp}[ extit{start}+1] = max( extit{nums}[ extit{start}], extit{nums}[ extit{start}+1]) & 只有两间房屋,偷窃其中金额较高的房屋 end{cases} ]

    计算得到 ( extit{dp}[ extit{end}])即为下标范围([ extit{start}, extit{end}])内可以偷窃到的最高总金额。

    分别取(( extit{start}, extit{end})=(0,n-2))(( extit{start}, extit{end})=(1,n-1))进行计算,取两个 ( extit{dp}[ extit{end}])中的最大值,即可得到最终结果。

    class Solution {
    public:
        static const int N=110;
        int f[N];
        
        int rob(vector<int>& nums) {
            int n=nums.size();
            if(n == 1) return nums[0];
            if(n == 2) return max(nums[0],nums[1]);
            return max(robRange(nums,0,n-2),robRange(nums,1,n-1));
        }
        
        int robRange(vector<int>& nums,int st,int ed) {
            f[st]=nums[st];
            f[st+1]=max(nums[st],nums[st+1]);
            for(int i=st+2;i<=ed;i++)
                f[i]=max(f[i-2]+nums[i],f[i-1]);
            
            return f[ed];
        }
    };
    
    
  • 相关阅读:
    作业5.1 四则运算----封装
    作业四
    作业2 (完)
    作业3
    作业二。。
    数独
    回答自己的提问
    《一个程序猿的生命周期》读后感
    阅读13-17章
    阅读10,11,12章
  • 原文地址:https://www.cnblogs.com/fxh0707/p/14669716.html
Copyright © 2020-2023  润新知