动态规划解题步骤:
1.确定状态表示:dp[i]是什么
2.确定状态转移方程:dp[i]等于什么
4.确定填表顺序:根据状态转移方程即可确定填表顺序
5.确定返回值
题目链接: 面试题 17.16. 按摩师 - 力扣(LeetCode)
题解1(斐波那契数列模型):
1.状态表示: dp[i]表示接受nums[i]预约的最优预约
2.状态转移方程:dp[i]=nums[i]+max(dp[i-2],dp[i-3]) 由于接受了nums[i]的预约,所以只能接受nums[i-2]或者nums[i-3]的预约
3.初始化:dp[0]=nums[0]、dp[1]=nums[1]、dp[2]=nums[0]+nums[2]
4.填表顺序:一维数组,从左向右填写
5.返回值:max(dp[n-1],dp[n-2]) 最优预约只能是接受最后一天或者倒数第二天预约
cpp
class Solution {
public:
int massage(vector<int>& nums) {
size_t n=nums.size();
//处理边界条件
if(n==0)
return 0;
if(n==1)
return nums[0];
if(n==2)
return max(nums[0],nums[1]);
if(n==3)
return max(nums[0]+nums[2],nums[1]);
//dp[i]表示最后一个预约是nums[i]的最优预约
//创建dp表
vector<int> dp(n);
//初始化
dp[0]=nums[0];
dp[1]=nums[1];
dp[2]=nums[0]+nums[2];
//填表
for(int i=3;i<n;++i)
{
dp[i]=nums[i]+max(dp[i-2],dp[i-3]);
}
//返回值
return max(dp[n-1],dp[n-2]);
}
};
题解2(简单多状态dp问题):
1.状态表示:有两个dp表,分别为f[i]和g[i],分别表示接受nums[i]预约和不接受nums[i]预约的最优预约
2.状态转移方程:f[i]=nums[i]+g[i-1] g[i]=max(f[i-1],g[i-1]) 接受nums[i]的预约,最佳预约就是再加上不接受前一个预约的最佳预约;不接受nums[i]的预约,最佳预约就是取接受或者不接受前一个预约的最大值
3.初始化:f[0]=nums[0] g[0]=0
4.填表顺序:一维数组,从左向右填写
5.返回值:max(f[n-1],g[n-1])
cpp
class Solution {
public:
int massage(vector<int>& nums) {
size_t n=nums.size();
//处理边界条件
if(n==0)
return 0;
//创建dp表
vector<int> f(n);
auto g=f;
//初始化
f[0]=nums[0];
g[0]=0;
//填表
for(int i=1;i<n;++i)
{
f[i]=nums[i]+g[i-1];
g[i]=max(f[i-1],g[i-1]);
}
return max(f[n-1],g[n-1]);
}
};