【Leetcode每日一题】 动态规划 - 简单多状态 dp 问题 - 按摩师(难度⭐)(64)

1. 题目解析

题目链接:面试题 17.16. 按摩师

这个问题的理解其实相当简单,只需看一下示例,基本就能明白其含义了。

2.算法原理

一、状态定义

在解决这类动态规划问题时,首先我们需要明确状态的定义。对于本题,我们定义两个状态数组来分别记录到达某个位置时,选择当前元素和不选择当前元素时的最长预约时长。

  • f[i]:表示选择到第i个位置时,且第i个元素nums[i]必须被选择的情况下的最长预约时长。
  • g[i]:表示选择到第i个位置时,且第i个元素nums[i]不被选择的情况下的最长预约时长。

这样的状态定义有助于我们处理在每个位置上的选择问题,即选择当前元素或不选择当前元素。

二、状态转移方程

接下来,我们需要根据状态定义推导出状态转移方程。

  • 对于f[i]:如果选择了第i个元素,那么前一个位置i-1的元素必然不被选择,因为不能连续选择两个元素。因此,f[i]的值应该等于g[i-1](即不选择第i-1个元素时的最长预约时长)加上当前元素的值nums[i]。即:f[i] = g[i - 1] + nums[i]

  • 对于g[i]:如果不选择第i个元素,那么前一个位置i-1的元素可以选择也可以不选择。因此,g[i]的值应该等于前一个位置选择或不选择两种情况下的最长预约时长的较大值。即:g[i] = max(f[i - 1], g[i - 1])

三、初始化

对于动态规划问题,合理的初始化是解决问题的关键。对于本题,我们根据题目要求和状态定义进行初始化。

  • 初始化f[0]nums[0],因为当只有一个元素时,必然选择该元素,其最长预约时长即为该元素的值。
  • 初始化g[0]为0,因为当只有一个元素时,如果不选择该元素,则最长预约时长为0。

四、填表顺序

根据状态转移方程,我们可以从左往右依次填充fg两个数组。因为每个位置的状态依赖于前一个位置的状态,所以必须按照从左到右的顺序进行填表。

五、返回值

最后,根据状态定义,我们需要返回选择到最后一个位置时的最长预约时长,即max(f[n-1], g[n-1])。因为在最后一个位置,我们可以选择该位置的元素也可以不选择,所以取两种情况下的较大值作为最终结果。

3.代码编写

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

The Last

嗯,就是这样啦,文章到这里就结束啦,真心感谢你花时间来读。

觉得有点收获的话,不妨给我点个吧!

如果发现文章有啥漏洞或错误的地方,欢迎私信我或者在评论里提醒一声~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

每天进步亿丢丢

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值