绪论
本章是 DP 的第三章,从第一章的简单理解 DP 的核心框架和写法及一维 DP,再到第二章的路径问题及二维 DP,到本章的多状态 DP 问题。本章将结合前面的所有基础引入多状态这个问题,并将由浅到深地从简单的打家劫舍两状态的 DP 到最后股票问题的四状态 DP 进行以练代学的方式学习。
打家劫舍
常见的思考是否使用打家劫舍问题时,遇见相邻问题不能选择此时就能思考是不是要使用打家劫舍。打家劫舍常使用两个 DP 表进行存储情况:
f[i]:选择 i 位置时的最大价值g[i]:不选择 i 位置时的最大价值
按摩师
题目
不能连续的选择,求找到最长的预约时长。
分析题目并提出解决方法
- 状态表示:(题意 + 经验 ——》从右往左)
dp[i]:选择到 i 位置的时候,此时的最长预约时长- 此处将 DP 分为两种状态:
f[i]:选择时的最长预约g[i]:不选择时的最长时长
- 状态转移方程:
- 选择 i 位置时(也就是
f[i]),那么就是要加上 i - 1 不选的最大值:f[i] = g[i-1] + nums[i] - 不选择 i 位置时(
g[i]),那么值就是前 i - 1 位置的选或者不选的最大值:g[i] = max(g[i-1], f[i-1])
- 选择 i 位置时(也就是
- 初始化:
- 因为要使用
f[i-1]&g[i-1],所以初始化f[0]&g[0] f[0] = nums[0](也就是直接填入第一个位置的时长即可)g[0] = 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;
;
f[] = nums[];
( i = ; i < n; i++) {
f[i] = g[i] + nums[i];
g[i] = (g[i], f[i]);
}
(g[n], f[n]);
}
};


