题目链接:面试题 17.16. 按摩师 - 力扣(LeetCode)
解法:
状态表示:
对于简单的线性 dp ,我们可以⽤「经验 + 题⽬要求」来定义状态表⽰:
- 以某个位置为结尾,巴拉巴拉;
- 以某个位置为起点,巴拉巴拉。
这里我们选择比较常用的⽅式,以某个位置为结尾,结合题⽬要求,定义⼀个状态表示:
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]) 。
- 初始化:
这道题的初始化比较简单,因此⽆需加辅助节点,仅需初始化
f[0] = nums[0], g[0] = 0 即可。
- 填表顺序
根据「状态转移方程」得「从左往右,两个表⼀起填」。
- 返回值
根据「状态表示」,应该返回
max(f[n - 1], g[n - 1])
。
代码:
C++:
java: