算法沉淀——动态规划之简单多状态 dp 问题(上)(leetcode真题剖析)

在这里插入图片描述

算法沉淀——动态规划之简单多状态 dp 问题上

  • 01.按摩师
  • 02.打家劫舍 II
  • 03.删除并获得点数
  • 04.粉刷房子

01.按摩师

题目链接:https://leetcode.cn/problems/the-masseuse-lcci/

一个有名的按摩师会收到源源不断的预约请求,每个预约都可以选择接或不接。在每次预约服务之间要有休息时间,因此她不能接受相邻的预约。给定一个预约请求序列,替按摩师找到最优的预约集合(总预约时间最长),返回总的分钟数。

注意:本题相对原题稍作改动

示例 1

输入: [1,2,3,1]

输出: 4

解释:选择 1 号预约和 3 号预约,总时长 = 1 + 3 = 4。

示例 2

输入: [2,7,9,3,1]

输出: 12

解释: 选择 1 号预约、 3 号预约和 5 号预约,总时长 = 2 + 9 + 1 = 12。

示例 3

输入: [2,1,4,5,3,1,1,3]

输出: 12

解释: 选择 1 号预约、 3 号预约、 5 号预约和 8 号预约,总时长 = 2 + 4 + 3 + 3 = 12。

思路

  1. 状态表达: 我们定义两个状态数组,fg

    • f[i] 表示:选择到位置 i 时,此时的最长预约时长,且 nums[i] 必须选。
    • g[i] 表示:选择到位置 i 时,此时的最长预约时长,nums[i] 不选。
  2. 状态转移方程: 对于 f[i]

    • 如果 nums[i] 必须选,那么我们仅需知道 i - 1 位置在不选的情况下的最长预约时长,然后加上 nums[i] 即可,因此 f[i] = g[i - 1] + nums[i]

    对于 g[i]

    • 如果 nums[i] 不选,那么 i - 1 位置上选或者不选都可以。因此,我们需要知道 i - 1 位置上选或者不选两种情况下的最长时长,因此 g[i] = max(f[i - 1], g[i - 1])
  3. 初始化: 由于这道题的初始化比较简单,无需加辅助节点,仅需初始化 f[0] = nums[0], g[0] = 0 即可。

  4. 填表顺序: 根据状态转移方程,从左往右,两个表一起填。

  5. 返回值: 根据状态表达,我们应该返回 max(f[n - 1], g[n - 1])

代码

class Solution {
public:int massage(vector<int>& nums) {int n = nums.size();if(n==0) return 0;vector<int> f(n);vector<int> g(n);f[0] = nums[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]);}
};

02.打家劫舍 II

题目链接:https://leetcode.cn/problems/house-robber-ii/

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

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

示例 1:

输入:nums = [2,3,2]
输出:3
解释:你不能先偷窃 1 号房屋(金额 = 2),然后偷窃 3 号房屋(金额 = 2), 因为他们是相邻的。

示例 2:

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

示例 3:

输入:nums = [1,2,3]
输出:3

提示:

  • 1 <= nums.length <= 100
  • 0 <= nums[i] <= 1000

思路

将环形的打家劫舍问题转化为两个单排的问题。具体来说,你分别考虑两种情况:

a. 偷第一个房屋的情况: 在这种情况下,由于首尾相连,你不能偷最后一个房子,因此偷窃范围是 [0, n - 2]。你可以使用之前解决「打家劫舍I」的动态规划方法来找到在这个范围内的最大金额,得到的结果是 x

b. 不偷第一个房屋的情况: 在这种情况下,你可以偷最后一个房子,因此偷窃范围是 [1, n - 1]。同样,使用相同的动态规划方法得到在这个范围内的最大金额,得到的结果是 y

最终的答案就是这两种情况下的最大值,即 max(x, y)

代码

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

03.删除并获得点数

题目链接:https://leetcode.cn/problems/delete-and-earn/

给你一个整数数组 nums ,你可以对它进行一些操作。

每次操作中,选择任意一个 nums[i] ,删除它并获得 nums[i] 的点数。之后,你必须删除 所有 等于 nums[i] - 1nums[i] + 1 的元素。

开始你拥有 0 个点数。返回你能通过这些操作获得的最大点数。

示例 1:

输入:nums = [3,4,2]
输出:6
解释:
删除 4 获得 4 个点数,因此 3 也被删除。
之后,删除 2 获得 2 个点数。总共获得 6 个点数。

示例 2:

输入:nums = [2,2,3,3,3,4]
输出:9
解释:
删除 3 获得 3 个点数,接着要删除两个 2 和 4 。
之后,再次删除 3 获得 3 个点数,再次删除 3 获得 3 个点数。
总共获得 9 个点数。

提示:

  • 1 <= nums.length <= 2 * 104
  • 1 <= nums[i] <= 104

思路

其实这道题可以看作是「打家劫舍I」问题的变体。通过将每个数字的出现的和记录在 hash 数组中,然后在 hash 数组上应用「打家劫舍」的思路,你能够有效地解决这个问题。

具体来说,可以创建一个大小为 10001(根据题目的数据范围)的 hash 数组,将 nums 数组中的每个元素 x 累加到 hash 数组下标为 x 的位置上。然后就可以使用「打家劫舍I」问题的动态规划方法,从 hash 数组中找到不相邻的元素的最大和。

代码

class Solution {
public:int deleteAndEarn(vector<int>& nums) {int hash[10001] = {0};for(int& x:nums) hash[x]+=x;vector<int> f(10001);vector<int> g(10001);for(int i=1;i<10001;++i){f[i]=g[i-1]+hash[i];g[i]=max(g[i-1],f[i-1]);}return max(f[10000],g[10000]);}
};

04.粉刷房子

题目链接:https://leetcode.cn/problems/JEj789/

假如有一排房子,共 n 个,每个房子可以被粉刷成红色、蓝色或者绿色这三种颜色中的一种,你需要粉刷所有的房子并且使其相邻的两个房子颜色不能相同。

当然,因为市场上不同颜色油漆的价格不同,所以房子粉刷成不同颜色的花费成本也是不同的。每个房子粉刷成不同颜色的花费是以一个 n x 3 的正整数矩阵 costs 来表示的。

例如,costs[0][0] 表示第 0 号房子粉刷成红色的成本花费;costs[1][2] 表示第 1 号房子粉刷成绿色的花费,以此类推。

请计算出粉刷完所有房子最少的花费成本。

示例 1:

输入: costs = [[17,2,17],[16,16,5],[14,3,19]]
输出: 10
解释: 将 0 号房子粉刷成蓝色,1 号房子粉刷成绿色,2 号房子粉刷成蓝色。最少花费: 2 + 5 + 3 = 10。

示例 2:

输入: costs = [[7,6,2]]
输出: 2 

提示:

  • costs.length == n
  • costs[i].length == 3
  • 1 <= n <= 100
  • 1 <= costs[i][j] <= 20

思路

  1. 状态表表示:

    • 在处理线性动态规划时,采用“经验+题目要求”方式定义状态表,选择以某个位置为结尾的方式。
    • 在该位置结束时,定义三种颜色选择的状态表,分别表示最后一个位置选择“红色”、“蓝色”和“绿色”的最小花费。
  2. 状态转移方程:

    • 分析三个状态的转移方程,以 dp[i][0] 为例:

      • 若选择在位置 i 粉刷“红色”,考虑前一个位置“蓝色”和“绿色”两种情况的最小花费,再加上当前位置的花费。
      • 类似地,对于 dp[i][1] dp[i][2],分别考虑选择“蓝色”和“绿色”时的最小花费。

      于是状态方程为:

      dp[i][0]=min(dp[i-1][1],dp[i-1][2])+costs[i-1][0];
      dp[i][1]=min(dp[i-1][0],dp[i-1][2])+costs[i-1][1];
      dp[i][2]=min(dp[i-1][0],dp[i-1][1])+costs[i-1][2];
      
  3. 初始化:

    • 添加一个辅助节点,将其初始化为 0,确保后续填表的正确性。
    • 注意辅助节点的值要符合题目的要求。
  4. 填表顺序:

    • 根据状态转移方程,从左往右同时填充三个表格。
  5. 返回值:

    • 返回最后一个位置三种颜色选择的最小值,即 min(dp[n][0], min(dp[n][1], dp[n][2]))

代码

class Solution {
public:int minCost(vector<vector<int>>& costs) {int n=costs.size();vector<vector<int>> dp(n+1,vector<int>(3));for(int i=1;i<=n;i++){dp[i][0]=min(dp[i-1][1],dp[i-1][2])+costs[i-1][0];dp[i][1]=min(dp[i-1][0],dp[i-1][2])+costs[i-1][1];dp[i][2]=min(dp[i-1][0],dp[i-1][1])+costs[i-1][2];}return min(dp[n][0],min(dp[n][1],dp[n][2]));}
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/701933.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

神经网络系列---常用梯度下降算法

文章目录 常用梯度下降算法随机梯度下降&#xff08;Stochastic Gradient Descent&#xff0c;SGD&#xff09;&#xff1a;随机梯度下降数学公式&#xff1a;代码演示 批量梯度下降&#xff08;Batch Gradient Descent&#xff09;批量梯度下降数学公式&#xff1a;代码演示 小…

基于Pytorch的猫狗图片分类【深度学习CNN】

猫狗分类来源于Kaggle上的一个入门竞赛——Dogs vs Cats。为了加深对CNN的理解&#xff0c;基于Pytorch复现了LeNet,AlexNet,ResNet等经典CNN模型&#xff0c;源代码放在GitHub上&#xff0c;地址传送点击此处。项目大纲如下&#xff1a; 文章目录 一、问题描述二、数据集处理…

[HTML]Web前端开发技术29(HTML5、CSS3、JavaScript )JavaScript基础——喵喵画网页

希望你开心,希望你健康,希望你幸福,希望你点赞! 最后的最后,关注喵,关注喵,关注喵,佬佬会看到更多有趣的博客哦!!! 喵喵喵,你对我真的很重要! 目录 前言 上一节的课后练习

docker运行onlyoffice,并配置https访问【参考仅用】

官方说明&#xff1a; Installing ONLYOFFICE Docs for Docker on a local server - ONLYOFFICEhttps://helpcenter.onlyoffice.com/installation/docs-developer-install-docker.aspx 一、容器端口、目录卷映射 sudo docker run --name容器名称 --restartalways -i -t -d -p…

#FPGA(基础知识)

1.IDE:Quartus II 2.设备&#xff1a;Cyclone II EP2C8Q208C8N 3.实验&#xff1a;正点原子-verilog基础知识 4.时序图&#xff1a; 5.步骤 6.代码&#xff1a;

零样本带解释性的医学大模型

带解释性的医学大模型 提出背景解法拆解方法的原因对比以前解法 零样本带解释性的医学大模型如何使用CLIP模型和ChatGPT来进行零样本医学图像分类用特定提示查询ChatGPT所生成的医学视觉特征描述相似性得分在不同症状上的可视化&#xff0c;用于解释模型的预测注意力图的可视化…

公众号回复idea能给出下载链接。

你可以使用字典来存储这些数据&#xff0c;然后在接收到消息时根据消息内容在字典中查找对应的回复内容。 这样做不仅可以更优雅地管理多组数据&#xff0c;还可以轻松地扩展和维护。msg parse_message(message) reply_dict {"idea": "https://pan.baidu.com/…

【数据结构】时间复杂度(加法乘法规则、渐近时间复杂度、循环时间复杂度总结

2.2 时间复杂度 什么是时间复杂度&#xff1f; 评估算法时间开销 T ( n ) O ( f ( n ) ) T(n)O(f(n)) T(n)O(f(n)) 在实际求解中&#xff0c;只留表达式中最高阶的部分&#xff0c;丢弃其他部分。 如何求解&#xff1f; 求解步骤 1.找到一个最深层的基本操作&#xff1b; 2.分…

03|分页查询优化

1. 根据自增且连续的主键排序 使用条件&#xff1a;主键连续且自增 & 结果按照主键排序 select * from employees limit 90000,5;理论上应该走主键索引, 为什么现在type是 all呢? ● 查询第9w行数据开始的5条数据时属于深度分页。 ● limit 90000 5工作原理就是先读取前面…

mac下使用jadx反编译工具

直接执行步骤&#xff1a; 1.创建 jadx目录 mkdir jadx2.将存储库克隆到目录 git clone https://github.com/skylot/jadx.git 3. 进入 jadx目录 cd jadx 4.执行编译 等待片刻 ./gradlew dist出现这个就代表安装好了。 5.最后找到 jadx-gui 可执行文件&#xff0c;双击两下…

C/C++暴力/枚举/穷举题目(刷蓝桥杯基础题的进!)

目录 前言 一、百钱买百鸡 二、百元兑钞 三、门牌号码&#xff08;蓝桥杯真题&#xff09; 四、相乘&#xff08;蓝桥杯真题&#xff09; 五、卡片拼数字&#xff08;蓝桥杯真题&#xff09; 六、货物摆放&#xff08;蓝桥杯真题&#xff09; 七、最短路径&#xff08;蓝…

Unity中URP实现水体效果(泡沫)

文章目录 前言一、给水上色1、我们在属性面板定义两个颜色2、在常量缓冲区申明这两个颜色3、在片元着色器中&#xff0c;使用深度图对这两个颜色进行线性插值&#xff0c;实现渐变的效果 二、实现泡沫效果1、采样 泡沫使用的噪波纹理2、控制噪波效果强弱3、定义_FoamRange来控制…

自定义神经网络二之模型训练推理

文章目录 前言模型概念模型是什么&#xff1f;模型参数有哪些神经网络参数案例 为什么要生成模型模型的大小什么是大模型 模型的训练和推理模型训练训练概念训练过程训练过程中的一些概念 模型推理推理概念推理过程 总结 前言 自定义神经网络一之Tensor和神经网络 通过上一篇…

yolov8添加注意力机制模块-CBAM

修改 在tasks.py&#xff08;路径&#xff1a;ultralytics-main/ultralytics-main - attention/ultralytics/nn/tasks.py&#xff09;文件中&#xff0c;引入CBAM模块。因为yolov8源码中已经包含CBAM模块&#xff0c;在conv.py文件中&#xff08;路径&#xff1a;ultralytics-…

业务流程管理系统(BPMS):一文掌握,组织业务流程优化必备。

大家好&#xff0c;我是大美B端工场&#xff0c;本期继续分享商业智能信息系统的设计&#xff0c;欢迎大家关注&#xff0c;如有B端写系统界面的设计和前端需求&#xff0c;可以联络我们。 一、什么是BPMS系统 BPMS是Business Process Management System&#xff08;业务流程管…

学习Python分支结构不走弯路

1.单分支语句 """ 语法&#xff1a; if 表达式:执行语句 执行流程&#xff1a;当表达式成立的时候&#xff0c;执行语句&#xff0c;否则不执行 """age int(input(请输入你的年龄&#xff1a;)) if age > 18:print(欢迎光临&#xff01;) …

二进制部署k8s集群之cni网络插件

目录 k8s的三种网络模式 pod内容器之间的通信 同一个node节点中pod之间通信 不同的node节点的pod之间通信 flannel网络插件 flannel的三种工作方式 VxLAN host-GW UDP Flannel udp 模式 Flannel VXLAN 模式 flannel插件的三大模式的总结 calico网络插件 k8s 组网…

ABC342 A-G

HUAWEI Programming Contest 2024&#xff08;AtCoder Beginner Contest 342&#xff09; - AtCoder 被薄纱的一场 A - Yay! 题意&#xff1a; 给出一串仅由两种小写字母构成的字符串&#xff0c;其中一种小写字母仅出现一次&#xff0c;输出那个仅出现一次的小写字母的位置…

PyTorch概述(五)---LINEAR

torch.nn.Linear torch.nn.Linear(in_features,out_features,biasTrue,deviceNone,dtypeNone) 对输入的数据应用一个线性变换&#xff1a; 该模块支持TensorFLoat32类型的数据&#xff1b;在某些ROCm设备上&#xff0c;使用float16类型的数据输入时&#xff0c;该模块在反向传…

文本左右对齐

题目链接 文本左右对齐 题目描述 注意点 words[i] 由小写英文字母和符号组成每个单词的长度大于 0&#xff0c;小于等于 maxWidth输入单词数组 words 至少包含一个单词要求尽可能均匀分配单词间的空格数量。如果某一行单词间的空格不能均匀分配&#xff0c;则左侧放置的空格…