iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > PHP编程 >60题学会动态规划系列:动态规划算法第三讲
  • 264
分享到

60题学会动态规划系列:动态规划算法第三讲

c++后端算法动态规划力扣 2023-10-05 17:10:18 264人浏览 泡泡鱼
摘要

简单多状态问题 文章目录 一.按摩师二.打家劫舍系列三.删除并获得点数四.粉刷房子 1.按摩师 力扣链接:力扣 一个有名的按摩师会收到源源不断的预约请求,每个预约都可以选择接或不接。在每次预约服务之间要有休息时间,因

简单多状态问题

文章目录

  • 一.按摩师
  • 二.打家劫舍系列
  • 三.删除并获得点数
  • 四.粉刷房子

1.按摩师

力扣链接:力扣

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

首先我们分析一下题目:1.每个预约可以选择接或者不接 2.不能接受相邻的预约。

状态表示

我们用dp[i]表示i位置的最长分钟数,而i位置又可以分为两种情况,一种是接,一种是不接,所以我们用两个dp表来表示状态。

f[i]表示接i位置的最长分钟数

g[i]表示不接i位置的最长分钟数 

状态转移方程

因为f[i]表示接i位置的预约,由于题目要求不能接受相邻的预约,所以我们一定不能接受i-1位置的预约,而g[i-1]就表示不接i-1位置的最长分钟数,又因为我们接了i位置要加上i位置的分钟数,所以

f[i] = g[i-1] + nums[i];

g[i]表示不接i位置,那么我们可以选择接受i-1位置或者不接受i-1位置,又因为我们要的是最大值,所以取这两种情况的较大值即可。

g[i] = max(f[i-1],g[i-1])

初始化

从状态转移方程来看,我们造成越界的位置只有f[0]和g[0],而f[0]表示接受0位置的最长分钟数,那么f[0] = nums[0]     g[0] = 0.

填表

已知f[0]和g[0]所以从左向右依次填表,两个表一起填

返回值

因为预约时长都是正数,所以越到后面时间越长,那么最长的只有两种情况:最后一个位置接或者最后一个位置不接,此题要求最大值,所以是这两个情况的较大值。

class Solution {public:    int massage(vector& nums) {       if (nums.size()==0) return 0;       //创建dp表       int n = nums.size();       vector f(n,0),g(n,0);       f[0] = nums[0],g[0] = 0;       for (int i = 1;i

 注意:此题会有nums.size()为0的情况,所以需要单独判断。

2.打家劫舍系列

打家劫舍I

力扣链接:力扣

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

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

 1.状态表示

由于每个位置存在偷与不偷两个状态,所以需要两个表来表示。

f[i]表示偷i位置的最高金额

g[i]表示不偷i位置的最高金额

状态转移方程

f[i] = g[i-1] + nums[i];

g[i] = max(f[i-1],g[i-1])

初始化,4.填表,5.返回值

与第一题同理。

对于这个题我们应该很熟悉吧,没错!和第一题按摩师简直一模一样,我们直接把按摩师的代码复制过来:

 相同的代码,立马就搞定了,我们将这道题拿出来是为了引出打家劫舍II和III,所以并不是没有用哦~

打家劫舍II

力扣链接:力扣

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

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

注意:和I不同的是,这道题的前后是一个圈,也就是说这是一个环形问题,下面我们来解决这道题。

首先我们能将问题分为两种情况,第一种是偷第一家的情况,第二种是不偷第一家的情况。

如果偷第一家,那么第二家和最后一家不能偷,也就是说我们只需要对2到n-2这个范围做一次打家劫舍I,最后加上nums【0】即可。

如果不偷第一家,那么1到n-1这个范围内可以随便偷,所以对1到n-1这个范围内做一次打家劫舍I即可。

class Solution {public:    int rob(vector& nums) {       int n = nums.size();       return max(nums[0]+rob1(nums,2,n-2),rob1(nums,1,n-1));    }    int rob1(vector& nums,int left,int right)    {        if (left>right) return 0;        int n = nums.size();        vector f(n, 0), g(n, 0);        f[left] = nums[left], g[left] = 0;        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]);    }};

 注意:当我们left大于right的时候那么一定是越界的情况,这种情况返回0即可。当我们将区间定为left到right这个闭区间,那么就从left+1开始填表,填到right,最后返回的时候也是返回dp表中right的位置,这里一定要画图映射位置关系。

3.删除并获得点数

力扣链接:力扣

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

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

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

 首先通过题目我们可以看到当我们删除X获取X的点数后,必须删除X-1和X+1的元素,我们发现这与打家劫舍的问题非常像,都是不能获得相邻元素的值,那么我们该如何将这个问题转化为打家劫舍问题呢?其实很简单,因为X-1 和 X 和 X+1这三个数都是相邻的,我们直接将nums映射到一个与下标同值的表中,比如3就放在下标为3的位置,并且给这个位置加上3,然后我们对这个新数组做一次打家劫舍就得到了最大点数。

比如实例2,映射后变成如下图:

然后我们对这个数组做一次打家劫舍,获取的最大点数就是9.

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

 此方法就是用空间换时间。

4.粉刷房子

力扣链接:力扣

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

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

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

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

 首先我们通过题目可以知道限制条件为:相邻房屋不能涂成同一个颜色,下面我们开始解题。

状态表示

dp【i】表示第i个房子所花费的最低成本,由于每个房子都可以涂成三种颜色,所以dp[i]又可以划分成3个状态。

dp[i][0]表示第i个房子涂成红色的最低成本

dp[i][1]表示第i个房子涂成蓝色的最低成本

dp[i][2]表示第i个房子涂成绿色的最低成本

状态转移方程

dp[i][0] = min(dp[i-1][1],dp[i-1][2]) + costs[i][0];

dp[i][1] = min(dp[i-1][0],dp[i-1][2]) + costs[i][1];

dp[i][2] = min(dp[i-1][0],dp[i-1][1]) + costs[i][2];

由于每个房子不能涂成相同颜色,所以第i层的房子如果是红色,那么第i-1层就只能是蓝色和绿色。

初始化

由于第一个房子不受前面任何房子的影响(i-1越界),所以第一个房子的三个状态都是已知的

dp[0][0] = costs[0][0],

dp[0][1] = costs[0][1],

dp[0][2] = costs[0][2];

填表

从左向右依次填表,三个表一起填

返回值

返回最后一个房子的三种状态的最小值。

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

当然我们也可以将最后取最小值的代码简化一下:

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

以上就是本篇文章的5道动态规划习题,还是建议大家在做动态规划习题的时候要多画图。

来源地址:https://blog.csdn.net/Sxy_wspsby/article/details/131175587

--结束END--

本文标题: 60题学会动态规划系列:动态规划算法第三讲

本文链接: https://www.lsjlt.com/news/423813.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 60题学会动态规划系列:动态规划算法第三讲
    简单多状态问题 文章目录 一.按摩师二.打家劫舍系列三.删除并获得点数四.粉刷房子 1.按摩师 力扣链接:力扣 一个有名的按摩师会收到源源不断的预约请求,每个预约都可以选择接或不接。在每次预约服务之间要有休息时间,因...
    99+
    2023-10-05
    c++ 后端 算法 动态规划 力扣
  • c++动态规划经典算法
    目录基本思想重要分析问题方法动态规划算法实例1、台阶问题2、从矩阵左上角走到右下角最短路径问题3、最大子数组问题4、最长公共子序列基本思想    &nb...
    99+
    2024-04-02
  • python动态规划算法怎么用
    小编给大家分享一下python动态规划算法怎么用,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!python有哪些常用库python常用的库:1.requesuts;2.scrapy;3.pillow;4.twisted;5...
    99+
    2023-06-14
  • java背包问题动态规划算法分析
    背包问题 【题目描述】 一个旅行者有一个最多能装 MM 公斤的背包,现在有 nn 件物品,它们的重量分别是W1,W2,…,WnW1,W2,…,Wn,它们的价值分别为C1,C2,…,C...
    99+
    2024-04-02
  • C++动态规划算法如何使用
    这篇“C++动态规划算法如何使用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“C++动态规划算法如何使用”文章吧。Fibon...
    99+
    2023-06-29
  • C++ 动态规划算法使用分析
    目录Fibonacci字符串分割(Word Break)三角矩阵(Triangle)路径总数(Unique Paths)最小路径和(Minimum Path Sum)Fibonacc...
    99+
    2024-04-02
  • c语言动态规划算法是什么
    C语言动态规划算法是一种用于解决优化问题的算法。它通过将问题划分为子问题,并保存子问题的解来避免重复计算,从而提高算法的效率。动态规...
    99+
    2023-08-18
    c语言
  • C++动态规划中关于背包问题讲解
    目录一、分割等和子集-最后一块石头的重量II二、目标和三、一和零四、零钱兑换II五、排列与组合组合总数IV(排列问题)零钱兑换(组合问题) 一、分割等和子集-最后一块石头的重量II ...
    99+
    2023-03-15
    C++动态规划背包问题 C++动态规划 C++背包问题
  • Java动态规划之丑数问题实例讲解
    问题描述: 我们把只包含质因子 2、3 和 5 的数称作丑数(Ugly Number)。求按从小到大的顺序的第 n 个丑数。 注: 1也是丑数 思路: 我们来分析一下丑数如何得到,肯...
    99+
    2024-04-02
  • Python算法题解:动态规划解0-1背包问题
    概述背包问题(Knapsack problem)是一种组合优化的NP完全问题。问题可以描述为:给定一组物品,每种物品都有自己的重量和价格,在限定的总重量内,我们如何选择,才能使得物品的总价格最高。问题的名称来源于如何选择最合适的物品放置于给...
    99+
    2023-06-02
  • Java实现动态规划背包问题
    目录前言一、原理1.1 最优子结构性质1.2 递归关系二、算法描述2.1 算法描述2.2 图解2.3 构造最优解三、 0 − 1 0-1 0−1 背包问题相关...
    99+
    2024-04-02
  • C++动态规划算法实现矩阵链乘法
    问题描述: 给定n个矩阵的链<A1,A2,…,An>,矩阵Ai的规模为p(i-1)×p(i) (1<=i<=n),求完全括号化方案,...
    99+
    2024-04-02
  • C++动态规划计算最大子数组
    目录例题1.求最大的子数组的和2.求和最大的相应子数组例题 题目:输入一个整形数组,数组里有正数也有负数。数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。求所有子数组...
    99+
    2024-04-02
  • java动态规划方法怎么使用
    这篇文章主要介绍了java动态规划方法怎么使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇java动态规划方法怎么使用文章都会有所收获,下面我们一起来看看吧。说明动态规划是一种编程原理,可以通过将非常复杂的问...
    99+
    2023-06-30
  • python实现动态规划算法的示例代码
    动态规划(Dynamic Programming,DP)是一种常用的算法思想,通常用于解决具有重叠子问题和最优子结构性质的问题。动态规划算法通常是将问题分解为子问题,先解决子问题,再...
    99+
    2023-02-16
    python 动态规划算法
  • Java使用动态规划算法思想解决背包问题
    目录动态规划算法动态规划算法的思想最优性原理动态规划算法的三大特点动态规划算法中的0/1背包问题动态规划算法的优点小结动态规划算法 动态规划算法的思想 动态规划算法处理的对象是多阶段...
    99+
    2024-04-02
  • Java矩阵连乘问题(动态规划)算法实例分析
    本文实例讲述了Java矩阵连乘问题(动态规划)算法。分享给大家供大家参考,具体如下:问题描述:给定n个矩阵:A1,A2,...,An,其中Ai与Ai+1是可乘的,i=1,2...,n-1。确定计算矩阵连乘积的计算次序,使得依此次序计算矩阵连...
    99+
    2023-05-30
    java 矩阵 算法
  • 【路径规划】局部路径规划算法——DWA算法(动态窗口法)|(含python实现 | c++实现)
    文章目录 参考资料1. DWA算法原理1.1 简介1.2 算法原理1. 速度采样2. 轨迹预测(轨迹推算)3. 轨迹评价 2. Python实现2.1 参数配置2.2 机器人运动学模...
    99+
    2023-08-31
    python 机器人 路径规划 DWA 动态窗口法
  • C++中的动态规划子序列问题分析探讨
    目录一、子序列(不连续)最长上升子序列最长公共子序列不相交的线二、子序列(连续)最长连续递增序列最长重复子数组最大子序和三、编辑距离判断子序列两个字符串的删除操作不同的子序列编辑距离...
    99+
    2023-03-15
    C++动态规划子序列 C++子序列问题 C++动态规划
  • C语言动态规划多种背包问题分析讲解
    目录写在前面01背包问题完全背包问题多重背包问题 I多重背包问题 II为什么可以这样优化呢一 、二进制与十进制二 、动态规划的时间复杂度估算三 、多重背包分组背包问题写在前面 之前讲...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作