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

【动态规划】简单多状态(一)

📝前言说明:

  • 本专栏主要记录本人的动态规划的学习以及LeetCode刷题记录,按专题划分
  • 每题主要记录:(1)本人解法 + 本人屎山代码;(2)优质解法 + 优质代码;(3)精益求精,更好的解法和独特的思想(如果有的话)
  • 文章中的理解仅为个人理解。如有错误,感谢纠错

🎬个人简介:努力学习ing
📋本专栏:C++刷题专栏
📋其他专栏:C语言入门基础,python入门基础,C++学习笔记,Linux
🎀CSDN主页 愚润泽

你可以点击下方链接,进行不同专题的动态规划的学习

点击链接开始学习
斐波那契数列模型路径问题
简单多状态(一)简单多状态(二)
子数组系列(一)子数组系列(二)
子序列问题(一)子序列问题(二)
回文串问题两个数组的dp问题(一)
两个数组的dp问题(二)01背包问题
完全背包二维的背包问题
其他

题目

  • 面试题 17.16. 按摩师
    • 优质解
  • 213. 打家劫舍 II
    • 优质解
  • 740. 删除并获得点数
    • 优质解
  • LCR 091. 粉刷房子
    • 个人解


面试题 17.16. 按摩师

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

在这里插入图片描述

优质解

思路:

  • 状态表示:dp[i] :选择到 i 位置时,此时的最⻓预约时⻓。
    • 但是,在我们进行状态表示的时候,根据题意:可以发现 dp[i] 出现了两种状态:当前位置被选和当前位置不被选。【这就是多状态,我们需要使用两个dp表】
    • f[i] 表⽰:选择到 i 位置时, nums[i] 必选,此时的最⻓预约时⻓
    • g[i] 表⽰:选择到 i 位置时,nums[i] 不选,此时的最⻓预约时⻓。
  • 状态转移方程
    • 对于 f[i]
      • 如果 nums[i] 必选,则i - 1 位置一定是不选的,因此 f[i] = g[i - 1] + nums[i]
    • 对于 g[i]
      • 如果 nums[i] 不选,那么 i - 1 位置可选 / 可不选。因此,我们需要知道 i - 1 位置上选或者不选两种情况下的最⻓时⻓,因此 g[i] = max(f[i - 1], g[i - 1])
  • 初始化:注意填写 0位置时,可能会越界,所以我们先填写f[0] == nums[0]g[0] == 0
  • 填表顺序:两个数组一起填,从左往右
  • 返回值: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, 0);auto g = f;f[0] = nums[0];for(int i = 1; i < n; i++){f[i] = g[i - 1] + nums[i];g[i] = max(g[i - 1], f[i - 1]);}return max(f[n - 1], g[n - 1]);}
};

时间复杂度:O(n)
空间复杂度:O(n)


213. 打家劫舍 II

题目链接:https://leetcode.cn/problems/house-robber-ii/description/
在这里插入图片描述
注意:数组中的首尾数字虽然相同,但是是不同的房间。


优质解

思路:

  • 把环形问题,拆成两个单排
    • 偷第⼀个房屋时,不能偷最后⼀个房⼦,因此就是偷 [0, n - 2] 区间的房⼦
    • 不偷第⼀个房屋时,可以偷最后⼀个房⼦,因此就是偷 [1, n - 1] 区间的房⼦

代码:

class Solution {
public:int rob1(vector<int>& nums, int left, int right){if(left > right) return 0;int n = nums.size();vector<int> f(n, 0);auto g = f;f[left] = nums[left];for(int i = left + 1; i <= right; i++){f[i] = g[i - 1] + nums[i];g[i] = max(f[i - 1], g[i - 1]);}return max(f[right], g[right]);}int rob(vector<int>& nums) {int n = nums.size();// 选 0,不选 1,不选 n - 1(下标)int x = nums[0] + rob1(nums, 2, n - 2);// 不选 0int y = rob1(nums, 1, n - 1);return max(x, y);}
};

时间复杂度:O(n)
空间复杂度:O(n)


740. 删除并获得点数

题目链接:https://leetcode.cn/problems/delete-and-earn/description/
在这里插入图片描述


优质解

思路:

  • 打家劫舍的变形:选了nums[i]就不能选nums[i] - 1nums[i] + 1(即:不能选数值相邻的两个)
  • 问题在于:打家劫舍的数组没有重复元素,而本题有
  • 我们只需:把相同的数字x累加到数组的x下标位置,其他位置设置成 0(然后做一次打家劫舍)

代码:

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

时间复杂度:O(n)
空间复杂度:O(n)


LCR 091. 粉刷房子

题目链接:https://leetcode.cn/problems/JEj789/description/
在这里插入图片描述

个人解

思路:

  • 三个dp(f, g, h)【当然用一个二维数组也行】, 表示当前房子粉刷成 红 / 蓝 / 绿 时的最小花费成本
  • 状态转移方程:f[i] = costs[i][0] + min(g[i - 1], h[i - 1]);
    • 代表第 i 个房子刷红色,前面取刷蓝 / 绿的最小值(其他同理)
  • 填表顺序:三个表并行填
  • 返回值:min(f[n - 1], g[n - 1], h[n - 1]);

用时:
屎山代码:

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

时间复杂度:O(n)
空间复杂度:O(n)


🌈我的分享也就到此结束啦🌈
要是我的分享也能对你的学习起到帮助,那简直是太酷啦!
若有不足,还请大家多多指正,我们一起学习交流!
📢公主,王子:点赞👍→收藏⭐→关注🔍
感谢大家的观看和支持!祝大家都能得偿所愿,天天开心!!!

http://www.xdnf.cn/news/8688.html

相关文章:

  • 77. Combinations
  • Qt实战:自定义QTreeWidget搜索隐藏显示项功能 | 附完整源码
  • 基于音频Transformer与动作单元的多模态情绪识别算法设计与实现(在RAVDESS数据集上的应用)
  • 算法、算力、数据哪个更重要
  • C#核心概念解析:析构函数、readonly与this关键字
  • java 代码查重(五)比较余弦算法、Jaccard相似度、欧式距离、编辑距离等在计算相似度的差异
  • 开发者工具箱-鸿蒙大小写转换开发笔记
  • H3C-WAF-单机部署
  • 【每天一个知识点】“数字人”(Digital Human)
  • Easy Dataset数据集构建使用
  • 解析 Flask 上下文机制:请求上下文、应用上下文
  • AI Agent开发第74课-解构AI伪需求的魔幻现实主义
  • 【c++】成员函数被声明为 `const` 时
  • Oracle 的SHRINK 操作实现原理
  • 软考学习中
  • Docker Swarm配置
  • Linux系统基础——是什么、适用在哪里、如何选
  • 模拟电子技术基础----绪论
  • Python 训练营打卡 Day 34
  • 前端流行框架Vue3教程:24.动态组件
  • vue3使用七牛云上传文件
  • MATLAB例程——基于分批运输与最近邻优化的垃圾运输路径规划,n个垃圾收集点,每点有固定垃圾量,车辆从处理厂出发收集垃圾后返回,目标是最小化总行驶距离
  • 洛谷B2144 阿克曼(Ackermann)函数
  • 互联网和以太网之是什么与区别
  • 2025年安克创新Anker社招校招入职测评 | 3天备考、自适应能力cata测评北森题库、安克创造者启航试炼、安克AI能力测评能力测评历年真题
  • Python协同过滤算法:从原理到实战应用
  • 数据库6——综合实验-水果商店进阶一
  • C++题解(33)2025年顺德区中小学生程序设计展示活动(初中组C++)U560876 美丽数(一)和 U560878 美丽数(二)题解
  • 优启通添加自定义浏览器及EXLOAD使用技巧分享
  • 安全语音通信系统python