【动态规划】速解简单多状态类问题

目录

17.16 按摩师

题⽬描述:

解法(动态规划):

1. 状态表⽰:

2. 状态转移⽅程:

3. 初始化:

4. 填表顺序

5. 返回值

代码

总结:

213.打家劫舍II(medium)

 题⽬描述:

 解法(动态规划)

代码:

740.删除并获得点数

题⽬描述:

 解法(动态规划):

代码:

剑指OfferI I091. 粉刷房⼦

题⽬描述:

解题思路:

代码:


17.16 按摩师

 //打家劫舍问题的变形~⼩偷变成了按摩师

题⽬描述:

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

解法(动态规划):

算法思路:

1. 状态表⽰:

对于简单的线性dp ,我们可以⽤「经验+题⽬要求」来定义状态表⽰:

  • i. 以某个位置为结尾,巴拉巴拉;
  • ii. 以某个位置为起点,巴拉巴拉。

这⾥我们选择⽐较常⽤的⽅式,以某个位置为结尾,结合题⽬要求,定义⼀个状态表⽰:

dp[i] 表⽰:选择到 i 位置时,此时的最⻓预约时⻓。

 但是我们这个题在 i 位置的时候,会⾯临「选择」或者「不选择」两种抉择,所依赖的状态需要 细分:

▪ 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);auto g = f;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]);}
};

总结:

213.打家劫舍II(medium)

 题⽬描述:

你是⼀个专业的⼩偷,计划偷窃沿街的房屋,每间房内都藏有⼀定的现⾦。这个地⽅所有的房屋都围成⼀圈,这意味着第⼀个房屋和最后⼀个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防 盗系统,如果两间相邻的房屋在同⼀晚上被⼩偷闯⼊,系统会⾃动报警。给定⼀个代表每个房屋存放⾦额的⾮负整数数组,计算你在不触动警报装置的情况下,今晚能够偷 窃到的最⾼⾦额。

//理解:就是不能两个房间连着偷,就还是f or g 的问题啦

 解法(动态规划)

算法思路: 这⼀个问题是「打家劫舍I」问题的变形。

上⼀个问题是⼀个「单排」的模式,这⼀个问题是⼀个「环形」的模式,也就是⾸尾是相连的。但 是我们可以将「环形」问题转化为「两个单排」问题

a. 偷第⼀个房屋时的最⼤⾦额x ,此时不能偷最后⼀个房⼦,因此就是偷[0, n - 2] 区间 的房⼦; b. 不偷第⼀个房屋时的最⼤⾦额y ,此时可以偷最后⼀个房⼦,因此就是偷[1, n - 1] 区 间的房⼦;

两种情况下的「最⼤值」,就是最终的结果。

因此,问题就转化成求「两次单排结果的最大值」。 

代码:

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 left, int right) {if (left > right)return 0;// 1. 创建 dp 表// 2. 初始化// 3. 填表// 4. 返回结果int n = nums.size();vector<int> f(n);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]);}
};

740.删除并获得点数

题⽬描述:

给你⼀个整数数组nums,你可以对它进⾏⼀些操作。每次操作中,选择任意⼀个nums[i],删除它并获得nums[i]的点数。之后,你必须删除所有等 于nums[i]-1 和nums[i]+1的元素。 开始你拥有0个点数。返回你能通过这些操作获得的最⼤点数。

 解法(动态规划):

算法思路: 其实这道题依旧是「打家劫舍I」问题的变型。

我们注意到题⽬描述,选择x 数字的时候, x - 1 与x + 1 是不能被选择的。像不像「打家 劫舍」问题中,选择i 位置的⾦额之后,就不能选择i - 1 位置以及i + 1 位置的⾦额呢~

因此,我们可以创建⼀个⼤⼩为10001 (根据题⽬的数据范围)的 hash 数组,将nums 数组中每⼀个元素x ,累加到hash 数组下标为x 的位置处,然后在hash 数组上来⼀次「打 家劫舍」即可。

代码:

class Solution {
public:int deleteAndEarn(vector<int>& nums) {const int N = 10001;// 1. 预处理//把没见过的往见过的上面靠int arr[N] = {0};for (auto x : nums)arr[x] += x;//记录重复数字的和// 2. 在 arr 数组上,做⼀次 “打家劫舍” 问题// 创建 dp 表vector<int> f(N);auto g = f;// 填表for (int i = 1; i < N; i++) {f[i] = g[i - 1] + arr[i];g[i] = max(f[i - 1], g[i - 1]);}// 返回结果return max(f[N - 1], g[N - 1]);}
};

 预处理:把没见过的往见过的上面靠~

剑指OfferI I091. 粉刷房⼦

题⽬描述:

假如有一排房子,共 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

解题思路:

代码:

class Solution {
public:int minCost(vector<vector<int>>& costs){int minCost(vector<vector<int>> & costs){// dp[i][j] 第i个房⼦刷成第j种颜⾊最⼩花费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][1], dp[i - 1][0]) + costs[i - 1][2];}return min(dp[n][0], min(dp[n][1], dp[n][2]));//只能两个一min
}
}
;

sum:

1.情况选择的表示:

两种:f or g

三种:二维数组

2.然后分别写出情况下的dp方程

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

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

相关文章

C++ 基于vs2019创建并使用动态链接库(dll)

库的基本认识 静态库&#xff08;Static Library&#xff09; 基本概念&#xff1a;静态库是在编译时链接到目标程序中的库文件。它包含了程序运行所需的所有函数和数据&#xff0c;这些函数和数据会被直接嵌入到最终生成的可执行文件中。静态库通常以.a&#xff08;在Unix-l…

分频器对相位噪声影响

本文我们将分析输入时钟被N分频之后的输出时钟的相位噪声如何变化。首先理想分频器的意思是我们假设分频器不会引入附加相位噪声&#xff0c;并且输入和输出时钟之间没有延时。我们假设每一个输出边沿的位置都完美的与输入边沿相对齐&#xff0c;这样便于分析。由于每N个输入时…

[FlareOn6]Overlong

很简单的逻辑 一度让我以为是加保护了 运行告诉我从未编码,懵逼 动调你也发现,你根本没什么可以操作的空间,密文什么的,都是固定的 但是这里大家发现没 我们只加密了28个密文 然后text是128 也就是 0x80 是不是因为密文没加密完呢 我也懒得去写代码了 汇编直接修改push 字…

axios和ts的简单使用

按照官网的使用案例简单记下笔记 1&#xff1a;安装 npm install axios 2&#xff1a;案例 一个简单的config配置信息 // 发起一个post请求 axios({method: post,url: /user/12345,data: {firstName: Fred,lastName: Flintstone} }); case // 在 node.js 用GET请求获取…

总结常见漏洞的代码审计方法

前言 这篇文章主要是总结一下在安全工作中常见漏洞的代码审计方法&#xff0c;以及修复方案&#xff0c;希望能对初学代码审计小伙伴们有所帮助&#xff0c;笔芯♥️ 代码审计的思路 通常做代码审计都是检查敏感函数的参数&#xff0c;然后回溯变量&#xff0c;判断变量是否可…

【Crypto】RSA

文章目录 题目步骤1.计算 &#x1d45b;2.计算欧拉函数 &#x1d719;(&#x1d45b;)3. 扩展欧几里得算法求逆元 &#x1d451; 解题感悟 题目 p473398607161 q4511491 e17 求d 步骤 1.计算 &#x1d45b; 公式&#xff1a;npq n47339860716145114912135733555619387051 …

初识STM32单片机-TIM定时器

初识STM32单片机-TIM定时器 一、定时器概述二、定时器类型2.1 基本定时器(TIM6和TIM7)2.2 通用定时器(TIM2、TIM3、TIM4和TIM5)2.3 高级定时器(TIM1和TIM8) 三、定时中断基本结构和时基单元工作时序3.1 定时器基本结构3.2 预分频器时序3.3 计数器时序3.3.1 计数器有无预装时序(…

Hono 框架使用经验谈

Hono&#x1f525;是一个小型、快速并开源的 Serverless Web 框架&#xff0c;用 TypeScript 写就。它适用于任何JavaScript运行时&#xff1a;Cloudflare Workers&#xff0c;Fastly ComputeEdge&#xff0c;Deno&#xff0c;Bun&#xff0c;Vercel&#xff0c;Netlify&#x…

动手学操作系统(一、搭建实验环境)

动手学操作系统&#xff08;一、搭建实验环境&#xff09; 文章目录 动手学操作系统&#xff08;一、搭建实验环境&#xff09;1. 在VMware虚拟机中安装ubuntu20.042. 安装Bochs3. 启动计算机Reference &#x1f680; 环境配置 &#x1f680; 笔者的环境使用的是 ubuntu 20.04…

python多线程的使用

Python 多线程探索 在 Python 编程中&#xff0c;多线程是一项强大的技术&#xff0c;它允许我们同时执行多个任务&#xff0c;从而提高程序的效率和响应性。 一、线程的基本概念 线程是进程中的一个执行单元&#xff0c;可以与其他线程共享进程的资源。 二、创建线程 在 P…

Linux:confluence8.5.9的部署(下载+安装+破ji)离线部署全流程

0.环境 Confluence也是比较吃运存了&#xff0c;我建议运行运存给到4g或者4g以上就可以了&#xff0c;核数可以给到1核或以上 我部署在centos7.9操作系统上&#xff0c;ip地址为&#xff1a;192.168.6.1&#xff0c;yum仓库使用的是自己的镜像文件&#xff0c;本章所有使用到…

爱普生XC1011SD为电气稳定控制系统组合式传感器推出解决方案

在现代电力系统中&#xff0c;确保系统的安全和稳定运行至关重要。为了应对这一需求&#xff0c;我们推出了XC1011SD组合式传感器解决方案&#xff0c;它专为电气稳定控制系统设计&#xff0c;提供了卓越的性能和可靠性。 XC1011SD是一款集成陀螺仪传感器和双轴加速度计于一体的…

炸裂!AI五分钟模仿爆款IP故事,涨粉速度太绝了!

‍ ‍大家好&#xff0c;我是向阳。 今天我要分享一个利用AI技术模仿爆款账号的小技巧&#xff0c;帮助大家迅速增加粉丝。这个方法简单实用&#xff0c;尤其适用于副业和本地生活领域。接下来&#xff0c;我将为大家详细讲解操作步骤。让我们开始吧。 副业赚钱&#xff1a;模…

合约构成-成员变量、函数、事件event、修饰器modifier及构造函数

合约的基本结构 合约中的成员变量合约中的成员函数Event&#xff08;事件&#xff09;、modifier(修饰器)与constructor&#xff08;构造函数:实例产生的时候执行&#xff09; Event事件 modifier construcor 1、成员变量 概念&#xff1a;存储合约状态的变量 声明方法&a…

北京证券公司港股通交易佣金手续费最低是多少?万0.8?港股通纳入规则是怎么样的?

港股通交易佣金概述 港股通的交易佣金可能会因证券公司和投资者的不同而有所差异。 北京证券公司的港股通交易佣金最低可能万分之零点八&#xff08;0.008%&#xff09;&#xff0c;但这需要投资者与证券公司客户经理了解&#xff0c;进行沟通和申请。 一般来说&#xff0c;…

CSS学习笔记:Less

什么是Less&#xff1f; Less是一个CSS预处理器&#xff0c; Less文件后缀是.less 扩充了CSS 语言&#xff0c;使CSS具备一定的逻辑性、计算能力 可以通俗地理解&#xff1a;Less是一种更好用的CSS 注释 运算 嵌套 Less嵌套的作用&#xff1a;快速生成后代选择器 变量 问…

软考中级-软件设计师-真题详解【2023年上半年】

2023上半年真题记忆点详解 本片不涉及解题法&#xff0c;只整理记忆背诵点&#xff0c;记住即可拿分。 上午题部分&#xff1a; 片内总线&#xff1a;用于芯片内部各主要部件连接&#xff1b; 系统总线&#xff1a;用于CPU、主存、外设见的数据传输&#xff1b; 通讯总线&…

04 FreeRTOS 队列(queue)

1、队列的特性 队列可以理解为一个传送带&#xff0c;一个流水线。 队列可以包含若干个数据&#xff1a;队列中有若干项&#xff0c;这被称为"长度"(length) 每个数据大小固定 创建队列时就要指定长度、数据大小 数据的操作采用先进先出的方法(FIFO&#xff0c;First…

干货分享 —— 如何开展web项目自动化测试!

前言 自动化(Automation)是指机器设备、系统或过程(生产、管理过程)在没有人或较少人直接参与的情况下&#xff0c;根据人的要求&#xff0c;通过自动检测、信息处理、分析判断、操纵和控制&#xff0c;达到预期目标的过程。自动化测试是指测试过程是在没有人为或较少人为干预…

从零构建vue3+ts+vite项目打包及项目依赖配置

❗️❗️❗️❗️ 写在最前: 本文是根据B站作者 月光分层 视频vuets 工程化配置以及作者笔记稍作整理 &#x1f496;&#x1f496;作者B站地址https://space.bilibili.com/14110850 &#x1f496;&#x1f496;视频教程地址vuets 工程化配置 &#x1f496;&#x1f496;作者微信…