动态规划(简单)
前言
纯个人笔记,记录自己动态规划学习次序与题目(大多为力扣的题目)方便复习查找。
本人学习使用的是c++,纯纯纯新手有写的不对的地方,非常欢迎来提醒
对于我这个新手来说大部分的题是很难做出来,肯定会借鉴相应的题解和解析,如果有争议,我会删除
第一题
题目
面试题 17.16. 按摩师
一个有名的按摩师会收到源源不断的预约请求,每个预约都可以选择接或不接。在每次预约服务之间要有休息时间,因此她不能接受相邻的预约。给定一个预约请求序列,替按摩师找到最优的预约集合(总预约时间最长),返回总的分钟数。
注意:本题相对原题稍作改动
示例 1:
输入: [1,2,3,1]
输出: 4
解释: 选择 1 号预约和 3 号预约,总时长 = 1 + 3 = 4。
示例 2:
输入: [2,7,9,3,1]
输出: 12
解释: 选择 1 号预约、 3 号预约和 5 号预约,总时长 = 2 + 9 + 1 = 12。
示例 3:
输入: [2,1,4,5,3,1,1,3]
输出: 12
解释: 选择 1 号预约、 3 号预约、 5 号预约和 8 号预约,总时长 = 2 + 4 + 3 + 3 = 12。
本题的意思是,例如[1,2,3,1],代表着4天,第一天有1个小时,第二天有2个小时,第三天有3个小时,第四天有1个小时,但是在不能连续选择的情况下,时间最长=1+3=4,选第一天和第三天。
代码
class Solution {
public:
int massage(vector<int>& nums)
{
if(nums.empty()) return 0;//考虑特殊情况,为空时,返回0
if(nums.size()==1) return nums[0];//nums长度为1,只有一个元素,则返回当前元素即可
int length=nums.size();
vector<int> dp(length);//定义一维数组
dp[0]=nums[0];
dp[1]=max(nums[0],nums[1]);
for(int i=2;i<length;i++)
{
dp[i]=max(dp[i-2]+nums[i],dp[i-1]);
}
return dp[length-1];
}
};
解释
1、dp的定义
因为替按摩师找到最优的预约集合 (总预约时间最长) 所以dp[i]代表在考虑下标 i (包含 i ) 的,最大时间。
2、递推公式
dp[i]=max(dp[i-2]+nums[i],dp[i-1]);
在下标 i 的时候可以考虑两种情况,选不选下标 i 的那天。
(1)如果选下标 i 的那天,则 i 的前一天不能再选,要从第 i-2 开始考虑 (因此她不能接受相邻的预约) ,就是在 i-2 之前的最大时间加上 i 的时间->dp[i-2]+nums[i];
(2)如果不选下标 i 的那天,则 i 的前一天能选,要从第 i-1 开始考虑,就是 i-1 之间的最大时间->dp[i-1];
因为是两种情况,所以两者之间取最大值->max(dp[i-2]+nums[i],dp[i-1]);
3、dp初始化
因为递推公式是由 dp[i-1] 和 dp[i-2] 决定的,所以初始化 dp[0] 和 dp[1] 。
dp[0]是考虑下标 0 及之前的最大时间->dp[0]=nums[0];
dp[1]表示下标为 1 及之前的最大时间,取两个数的最大值->dp[1]=max(nums[0],nums[1]);