【动态规划】打家劫舍类问题

ops/2024/11/14 8:22:56/

一、按摩师

17.16. 按摩师

题目描述:

题目分析:

1、状态表示

每个预约都只会有两种选择,即选或不选。因此我们可以用 

  • dp[i][0] 表示不选择第 i 个预约时,最长的预约时长
  • dp[i][1] 表示选择第 i 个预约时,最长的预约时长

2、状态转移方程

对于 dp[i][0] :

  • 如果我们选择了第 i 个预约,那么第  i-1 次预约就一定不会选择,这时我们只需要知道不选第 i-1 次预约时的最长预约时长即可,即 dp[i-1][0] 的值,再加上 num[i]  即可。可得递推公式就为:

        dp[i][1]=dp[i-1][0]+nums[i]

对于 dp[i][1] :

  • 如果我们不选择第 i 个预约,那么第  i-1 次预约就可以被选择,当然也可以不选,这时我们只需要知道选或不选第 i-1 次预约时分别的最长预约时长即可,即 dp[i-1][0] 与 dp[i-1][0] 的值,取这两个中的最大值即可。可得递推公式就为:

       dp[i][0]=Math.max(dp[i-1][1],dp[i-1][0])

3、初始化

为了避免 i-1 时越界,我们初始化dp表的长度为 n+1,然后从 i=1 开始遍历

要注意下标的映射关系,此时 nums[i-1] 表示nums中第 i 个元素

4、返回值

直接返回 Math.max(dp[n][0],dp[n][1]),因为我们不确定最后一个选不选。

代码实现:

java">class Solution {public int massage(int[] nums) {int n=nums.length;int[][] dp=new int[n+1][2];for(int i=1;i<=n;i++){dp[i][0]=Math.max(dp[i-1][1],dp[i-1][0]);dp[i][1]=dp[i-1][0]+nums[i-1];}return Math.max(dp[n][0],dp[n][1]);}
}

二、打家劫舍 II

213. 打家劫舍 II

题目描述:

题目分析:

其实这就是在上题的基础上做了一些限制。我们可以根据第一号房子是否选择来将问题抽象成两个模型:

  • 偷第一号房子:此能就不能去偷第二号房子与第n号房子,就是还能偷 [3,n-1] 区间内的房子
  • 不偷第一号房子:此时可以偷最后一个房子,也就是说可以偷 [2,n] 区间内的房子

我们可以将上题中的 “打家劫舍” 模型抽象出来,将求取 [1,n] 范围内的最优选改为设定的 [l,r] 范围内的最优选。只需要修改一下遍历时的边界即可

此时就将该问题抽象成了两个 “打家劫舍” 问题的最优解了。

代码实现:

java">class Solution {public int rob(int[] nums) {int n=nums.length;return Math.max(nums[0]+fun(nums,3,n-1),fun(nums,2,n));}public static int fun(int[] nums,int l,int r){int[][] dp=new int[nums.length+1][2];for(int i=l;i<=r;i++){dp[i][0]=Math.max(dp[i-1][0],dp[i-1][1]);dp[i][1]=dp[i-1][0]+nums[i-1];}return Math.max(dp[r][0],dp[r][1]);}}

三、删除并获得点数

740. 删除并获得点数

题目描述:

题目分析:

这题看上去似乎与 “打家劫舍” 毫不相关。但仔细观察我们会发现,当选择值为 num[i] 的数字时, num[i] -1与 num[i] +1就无法被选中了。这与不能连续选择元素的 “打家劫舍” 问题不谋而合

我们可以创建一个hash数组,将 num[i] 的值映射到 hash数组对应的下标。然后再对hash数组进行一次 “打家劫舍” 即可

代码实现:

java">class Solution {public int deleteAndEarn(int[] nums) {int[] arr=new int[10001];for(int num:nums){arr[num]+=num;}int[] f=new int[10001],g=new int[10001];f[0]=arr[0];for(int i=1;i<10001;i++){f[i]=g[i-1]+arr[i];g[i]=Math.max(f[i-1],g[i-1]);}return Math.max(f[10000],g[10000]);}
}

四、粉刷房子

LCR 091. 粉刷房子

题目描述:

题目分析:

这个问题其实就是拓展版的 “打家劫舍” 问题。普通的 “打家劫舍” 问题每个状态只有 选与不选 两种,而该题有三种。但其实万变不离其中,仔细分析每种状态也能很好地做出来。

1、状态表示

  • 用 r[i] 表示第 i 个位置选择红色时的最小花费
  • 用 b[i] 表示第 i 个位置选择篮色时的最小花费
  • 用 g[i] 表示第 i 个位置选择绿色时的最小花费

2、状态转移方程

由于每个位置都有三种选择,也就对应了三种状态:

对于 r[i] :

  • 如果第 i 个位置刷上红色,那么第 i-1 个位置上就只能刷 蓝色或绿色。因此我们只需要知道第 i-1 个位置刷上 蓝色或绿色 这两种情况中的最小花费,再加上 i 位置的花费即可。可得状态转移方程就为:

        r[i]=Math.min(b[i-1],g[i-1])+costs[i][0]

同理可以得出另外两种状态转移方程为:

        b[i]=Math.min(r[i-1],g[i-1])+costs[i][1]
        g[i]=Math.min(r[i-1],b[i-1])+costs[i][2]

4、初始化

为了避免 i-1 发生越界访问,我们可以先初始化当 i=0 时每种情况的初始值。而由于是首次选择,因此每组的最小花费就应该为对应的costs本身:

        r[0]=costs[0][0]
        b[0]=costs[0][1]
        g[0]=costs[0][2]

代码实现:

java">class Solution {public int minCost(int[][] costs) {int n=costs.length;int[] r=new int[n],b=new int[n],g=new int[n];r[0]=costs[0][0];b[0]=costs[0][1];g[0]=costs[0][2];for(int i=1;i<n;i++){r[i]=Math.min(b[i-1],g[i-1])+costs[i][0];b[i]=Math.min(r[i-1],g[i-1])+costs[i][1];g[i]=Math.min(r[i-1],b[i-1])+costs[i][2];}return Math.min(r[n-1],Math.min(b[n-1],g[n-1]));}
}


那么本篇文章就到此为止了,如果觉得这篇文章对你有帮助的话,可以点一下关注和点赞来支持作者哦。如果有什么讲的不对的地方欢迎在评论区指出,希望能够和你们一起进步✊


http://www.ppmy.cn/ops/133513.html

相关文章

TensorFlow 2.0 环境配置

官方文档&#xff1a;CUDA Installation Guide for Windows 官方文档有坑&#xff0c;windows的安装指南直接复制了linux的指南内容&#xff1a;忽略这些离谱的信息即可。 可以从官方文档知悉&#xff0c;cuda依赖特定版本的C编译器。但是我懒得为了一个编译器就下载整个visua…

微信小程序进行md5加密 ,base64 转码

封装一个Md5加密的工具 &#xff1a; utils /md5.js function md5(string) { function md5_RotateLeft(lValue, iShiftBits) { return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits)); } function md5_AddUnsigned(lX, lY) { var lX4, lY4, l…

ArcGIS Pro属性表乱码与字段名3个汉字解决方案大总结

01 背景 我们之前在使用ArcGIS出现导出Excel中文乱码及shp添加字段3个字被截断的情况&#xff0c;我们有以下应对策略&#xff1a; 推荐阅读&#xff1a;ArcGIS导出Excel中文乱码及shp添加字段3个字被截断&#xff1f; 那如果我们使用ArGIS Pro出现上述问题&#xff0c;该如何…

【蓝桥等考C++真题】蓝桥杯等级考试C++组第13级L13真题原题(含答案)-跳绳

CL13 跳绳 小蓝的班进行比赛跳绳。已知班里共有学生 n 名:给定学生的跳绳成绩(1 分钟跳绳的个数): 请将这 n 名学生的跳绳成绩从高到低排序后输出。输入 共 2 行&#xff1b; 第 1 行是一个正整数 n(1<n<100)&#xff1b; 第 2 行有 n 个正整数(小于 1000)&#xff1a;…

Linux笔记-对Linux环境变量的进一步认识(2024-08-09)

此篇公开到互联网上的时间是&#xff1a;2024-11-11 主要是PATH和LD_LIBRARY_PATH。 基本概念 在 Linux 中&#xff0c;PATH 和 LD_LIBRARY_PATH 是两个不同的环境变量&#xff0c;它们的作用和使用场景有所不同。 PATH 作用&#xff1a;用来指定可执行文件的搜索路径。当你…

c++中异常处理

一、C 中的异常处理机制 基本原理&#xff1a;C 异常处理机制提供了一种在程序运行期间处理错误和异常情况的结构化方式。它基于 try、catch 和 throw 三个关键字来实现。当程序中出现异常情况时&#xff0c;可以使用 throw 表达式抛出一个异常对象&#xff0c;然后在可能捕获…

SystemC学习(4)— 在VCS中运行SystemC

SystemC学习&#xff08;4&#xff09;— 在VCS中运行SystemC 一、前言 参考&#xff1a;VCS编译verilog&SystemC 二、仅包含SystemC的仿真 源文件使用上一篇&#xff1a;SystemC学习&#xff08;3&#xff09;— APB_SRAM的建模与测试 编写makefile如下所示&#xff…

数据库参数备份

MySQL #!/bin/bash # 获取当前日期和时间的时间戳 TIMESTAMP$(date "%Y%m%d-%H%M%S")# 0、创建目录 mkdir /tmp/parameter_$TIMESTAMP/# 1、获取所有命名空间 echo "1、获取所有命名空间" NAMESPACES$(kubectl get ns | grep qfusion- | grep -v qfusion-…