当前位置: 首页 > article >正文

动态规划【打家劫舍】

今天和大家分享一下动态规划当中的打家劫舍题目,希望在大家刷题的时候提供一些思路

打家劫舍1:

题目链接:  198. 打家劫舍 - 力扣(LeetCode)

题目描述:

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

给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。

示例 1:

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

动规5部曲:

  1. 确定dp数组(dp table)以及下标的含义
  2. 确定递推公式
  3. dp数组如何初始化
  4. 确定遍历顺序
  5. 举例推导dp数组

dp数组的含义:

当前下标所对应的下标所对应的最大可以偷窃的金钱

确定递推公式:

根据dp数组的含义可得,我们当前的金额最大值就是上一个房间可以偷窃的最大值和当前数值和上上一个房间可以偷窃的最大数值之和

dp数组如何初始化:

考虑最简单的情况,假如只有一间房间,当前的dp[0]就是num[0],如果只有两间房,那么当前的dp[0]为num[0],dp[1]为max(num[0],num[1])

确认遍历顺序:

只遍历房间

举例推导dp数组:

房子编号:     1    2    3    4    5
金额 (nums):   2    7    9    3    1

动态规划过程 (dp):
dp[0] = 2             (偷第一个房子)
dp[1] = max(2, 7) = 7 (偷第二个房子)

dp[2] = max(7, 2+9) = 11
dp[3] = max(11, 7+3) = 11
dp[4] = max(11, 11+1) = 12

最终最大金额: dp[4] = 12

假设数组为num,那么dp[0]为num[0],dp[1]为max(num[0],num[1]),通过遍历我们的房屋,那么就可以得到dp[i]=max(dp[i-1],dp[i]+dp[i-2])

思维讲解:

 详细了解dp数组的含义,我们这里每次dp取到的都是当前房间和前面房间可以偷窃的金钱最大数,所以当前dp值就是上一个dp或者num[i]+dp[i-2] ,从而通过遍历房间得到我们的dp

代码:

int rob(vector<int>& nums) {
        vector<int> dp(nums.size() + 1, 0);
        if(nums.size()<2) return nums[0];
        dp[0] = nums[0];
        dp[1] = max(nums[0],nums[1]);
        for (int i = 2; i < nums.size(); i++) {
            dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);
        }
        return dp[nums.size()-1];
    }
打家劫舍2:

题目链接: 213. 打家劫舍 II - 力扣(LeetCode)

题目描述:

你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。

给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,今晚能够偷窃到的最高金额。

示例 2:

输入:nums = [1,2,3,1]
输出:4
解释:你可以先偷窃 1 号房屋(金额 = 1),然后偷窃 3 号房屋(金额 = 3)。
     偷窃到的最高金额 = 1 + 3 = 4 。

 这个题目比前面的那个多了一个条件,就是房屋是一个环形的房间,那么这个题目怎么解决呢,如何进行初始化呢,选上第一个就不能选上最后一个,如何解决这个问题呢

因为这是一个环形房间,从哪里开始都一样,我们可以将房间分为两组,第一组就是从第一个房间到倒数第二个房间,然后第二组就是第二个房间到倒数第一个房间,然后得出这两组所求的最大金额,返回的就是两组当中最大金额的最大值,第几个到第几个的房间偷取的最大金钱数和打家劫舍1情况相同

为什么要这样想呢??? 

因为这里有两种情况:

1. 不偷最后一个房子

假设我们从第一个房子开始偷,这样就不需要考虑偷最后一个房子,因为它与第一个房子相邻。因此,问题就简化为一个普通的“打家劫舍”问题,即我们从第 1 个房子到第 n-1 个房子之间选择哪些房子偷。这个问题可以通过动态规划来解决。

2. 不偷第一个房子

假设我们从第二个房子开始偷,这样就不需要考虑偷第一个房子,因为它与第二个房子相邻。因此,这样的问题就变成了从第 2 个房子到第 n 个房子之间选择偷哪些房子。同样可以通过动态规划来解决。

 

 

最后通过比较11打于10所以选11,所能偷窃的最大金额为11 

代码:

class Solution {
public:
    int rob(vector<int>& nums) {
        if (nums.size() == 0)
            return 0;
        if (nums.size() == 1)
            return nums[0];
        if (nums.size() == 2)
            return max(nums[0], nums[1]);
        vector<int> dp1(nums.size(), 0);
        vector<int> dp2(nums.size(), 0);

        dp1[0] = nums[0];
        dp1[1] = max(nums[0], nums[1]);
        dp2[1] = nums[1];
        dp2[2] = max(nums[1], nums[2]);

        for (int i = 2; i < nums.size() - 1; i++) {
            dp1[i] = max(dp1[i - 2] + nums[i], dp1[i - 1]);
        }
        for (int i = 3; i < nums.size(); i++) {
            dp2[i] = max(dp2[i - 2] + nums[i], dp2[i - 1]);
        }
        return max(dp1[nums.size() - 2], dp2[nums.size() - 1]);
    }
};

 后面会继续补充的,感谢观看


http://www.kler.cn/a/500856.html

相关文章:

  • [SMARTFORMS] 导出SMARTFORMS表单数据
  • 【2024年华为OD机试】 (A卷,100分)- 二元组个数(Java JS PythonC/C++)
  • 给DevOps加点料:融入安全性的DevSecOps
  • Unity + Firebase + GoogleSignIn 导入问题
  • HTTP 入门:认识网络通信基础
  • Node.js——fs(文件系统)模块
  • 【python爬虫入门教程13--selenium的自动点击 --小小案例分享】
  • 挖掘用户价值:链动2+1模式、AI智能名片与S2B2C商城小程序的应用研究
  • tensor core实现flash_attn_mma_share_kv源码分析
  • WebSocket、SSE(Server-Sent Events)、HTTP 和 Axios关系总结
  • openEuler安装docker
  • 做一个 简单的Django 《股票自选助手》显示 用akshare 库(A股数据获取)
  • SpringBoot整合Easy-es
  • 计算机网络之---防火墙与入侵检测系统(IDS)
  • 【Rust自学】11.9. 单元测试
  • Kafka 深度剖析
  • MySQL 17 章——触发器
  • CSS圆形序号简单案例
  • 云原生时代的IT运维:从工具到方法论的全面升级
  • Service Work离线体验与性能优化
  • 【开发环境搭建篇】Visual Studio 2022 安装和使用
  • Docker运行hello-world镜像失败或超时
  • netplan apply报错No module named ‘netifaces‘
  • 【力扣Hot100】哈希表
  • 第34天:安全开发-JavaEE应用反射机制攻击链类对象成员变量方法构造方法
  • PHP cURL 函数初学者完全指南