动态规划系列--刷题笔记(思路整理)

前言:

本科的时候,动态规划学得懵懵懂懂,不清不楚,给我留下了一些心理阴影。但由于其重要性,还是得刷一刷动态规划的题,我打算做一个刷题日记,尽量把自己找状态转移方程的思路都整理出来,以备不时之需。加油,算法小白冲冲冲!

题目特点:(借的图)

动态规划系列--刷题笔记(思路整理)_第1张图片

题目类型:(借的图)

动态规划系列--刷题笔记(思路整理)_第2张图片

解题套路:(根据九章算法总结而来)

1、确定状态(弄清楚状态的含义):①找最后一步 ②转化为子问题

2、根据子问题的转化过程,确定状态转移方程

3、确定初始条件和边界情况

4、弄清楚状态计算顺序


开始做题!!

1、面试题17.16 按摩师 (最值问题)

动态规划系列--刷题笔记(思路整理)_第3张图片

分析:

1)确定状态:设f(n)=在0~n中取得最大的总预约时间,那么其最后一步,即为f(n-1)=max[f(n-3)+a[n-1],f(n-4)+a[n-2]],翻译一下,f(n-1)即为最终的解,它在最后一次必定取a[n-1]或者取a[n-2],由于预约必须隔开,取前者时则需要加上0~n-3序列的最大总预约时间f(n-3),取后者时则需要加上0~n-4序列的最大预约时间f(n-4),两者中取一个max。这样,就转化成了子问题。

2)状态转移方程:dp[i]=max(dp[i-2]+nums[i],dp[i-3]+nums[i-1]);

3)边界条件:dp[0]=nums[0],dp[1]=max(nums[0],nums[1]),dp[2]=max(nums[0]+nums[2],nums[1]);

我的代码:

class Solution {
public:
    int massage(vector& nums) {
        int len=nums.size();
        if(len==0) return 0;
        else if(len==1) return nums[0];
        else if(len==2) return max(nums[0],nums[1]);
        else if(len==3) return max(nums[0]+nums[2],nums[1]);
        
        vector ans(len,0);
        ans[0]=nums[0];
        ans[1]=max(nums[0],nums[1]);
        ans[2]=max(nums[0]+nums[2],nums[1]);
        for(int i=3;i

 

2、除数博弈(存在性问题)

动态规划系列--刷题笔记(思路整理)_第4张图片

分析:

1)确定状态:设f(n)=在数为n时Alice取得胜利,那么最后一步,我考虑的是如果能保证f(n)时Alice成功,且f(n-x)时bob失败,那么Alice即可取得胜利。

2)状态转移方程:dp[i] = !dp[i] && (i%x==0) && 0

3)边界条件:dp[1]=false,dp[2]=true;

我的代码:

class Solution {
public:
    bool divisorGame(int N) {
        vector dp(1001,false);
        dp[1]=false;
        dp[2]=true;
        for(int i=3;i<=N;++i){
            for(int j=1;j

另外,该题有一个超级简单的做法,找规律...

先看代码就知道为什么说超级简单了,再上官方解释

class Solution {
public:
    bool divisorGame(int N) {
        return N%2==0;
    }
};

动态规划系列--刷题笔记(思路整理)_第5张图片

 

3、使用最小花费爬楼梯

动态规划系列--刷题笔记(思路整理)_第6张图片

分析:

这个题目初看较为简单,做的过程中,我感觉坑在状态f(x)的定义上,我很容易就被绕晕了。因此,配上一张借来的图,帮助更好地说明该题的状态定义问题。

动态规划系列--刷题笔记(思路整理)_第7张图片

1)确定状态:设f(n)=爬上n层顶部的最小花费。由此,如图所示,第i层则是i-1层的顶部,由此爬到第i层等同于爬到第i-1层顶部,根据状态定义,此时的花费应当是cost[i-1]。再确定最后一步,到第i层顶部有两种可能性,一种是从第i层开始爬一层,即为f(i-1)+cost[i],另一种是从第i-1层开始爬两层,即为f(i-2)+cost[i-1],两者中取最小值。

2)状态转移方程:dp[i]=min(dp[i-2]+cost[i-1],dp[i-1]+cost[i])

3)边界条件:dp[0]=0,  dp[1]=min(cost[0],cost[1])

我的代码:

class Solution {
public:
    int minCostClimbingStairs(vector& cost) {
        int len=cost.size();
        if(len==0) return 0;
        else if(len==1) return cost[0];

        vector dp(len,INT_MAX);
        dp[0]=0; dp[1]=min(cost[0],cost[1]);
        for(int i=2;i

 

4、

你可能感兴趣的:(动态规划,算法,leetcode,c++)