DFS 记忆化 - wenzhoullq/leetcode GitHub Wiki

分析

记忆化dfs等同于dp,因此将它从回溯中取走;它通过建立一个coach数组来记忆化存储,减少回溯的次数,降低时间复杂度;值得注意的是,这种记忆化的coach是只在乎后续内容,至于前面的内容如何是不会加入到coach中的,并且前面的内容不会影响后续dfs,因此在dfs的过程中,很多都是**空值(如0,new )**去当参数。

重要点在于coach的构造,可能涉及压缩算法,可能涉及字符串的拼接,可能涉及三维(三维主要和dp的类型有关),以及dfs的类型的判断,是长度型,存在型还是数量型,其中coach和dfs是一个类型的,而dfs和主函数是一个类型

dfs简单易懂,但是记忆化dfs有个致命的弱点:当n>=1e9时且存在三个dfs会超时,因此需要化作动态规划的形式或则将一个dfs()优化掉

对于树形DP的记忆化,需要一个map储存root节点

分类

题目可以从两个角度进行分类,一个是从返回值的类型来分类,另一种是从dp的种类来分类

数量型

模板

    coach=-1;//这里需要注意的是,有可能遇到不满足的情况,因此需要初始化为-1;
    int dfs(){
        //如果coach被访问过,返回访问值
        if(到末端){
           if(满足) return 1;
           return 0;
        }
        
        int temp=0;//为什么设置temp=0来求,因为可能存在服务不满足的情况
        for(){
           if(不满足) continue;//这里的不满足和上面的不满足两者取其一,如何选择呢?一般来说,如果涉及到前值得比较,那么在这里比较;如果是不涉及,一般选择上方
           temp+=dfs();
          }
        dp[i]=temp ;//
        主要是判断何时满足才能方案数+1,这个是重点.
        return dp[i];
    }

题目

  • 费用型

638. 大礼包 全是自买和全是礼包之间的抉择

  • 方案数型

LCP 64. 二叉树灯饰树形DP,同时还有打开多个的操作

[NOIP2008]传球游戏 (用dp更快)

576. 出界的路径数

1444. 切披萨的方案数

1575. 统计所有可行路径

6110. 网格图中递增路径的数目

6168. 恰好移动 k 步到达某一位置的方法数目

存在型

题目

139. 单词拆分

802. 找到最终的安全状态

2267. 检查是否有合法括号字符串路径

长度型

模板

一般用于最大/最长用这个模板,如果是最短/最小的话以bfs居多,非要用记忆化DFS的话,则是记录step+1慢慢剪枝

    int dfs(int index){
        //如果coach被访问过,返回访问值
        //如果到边缘,边缘处理
        int sum=1;
        for(int i=index,i<len;i++)
        sum=Math.max(dfs()+1,sum);//长度型的精髓在于这个+1
        //coach赋值
        return sum;
    }

题目

  • 最大/长

397. 整数替换

329. 矩阵中的最长递增路径

1387. 将整数按权重排序

1553. 吃掉 N 个橘子的最少天数 这题非常坑,第一个坑是如果按照模板来,空间复杂度会超时,因此需要简化dfs(n-1)+1部分,而这个简化是含有贪心思想;第二个坑是int[]的长度范围,需要用HashMap替代

  • 最小/短

1293. 网格中的最短路径

字符串型

题目

140. 单词拆分 II

三个dfs会超时

要么想办法优化掉一个dfs,要么用dp

题目

1553. 吃掉 N 个橘子的最少天数

面试题 08.01. 三步问题

dp角度

从dp角度分类记忆化dfs

状压dp

题目

区间dp

区间DP分为1维区间和2维区间;另外一种是取后对原排列有影响的,此时又是另一种构建方法

模板

    int dfs(int left,int right){
        //如果coach被访问过,返回访问值
        //如果到边缘,边缘处理
        int sum=0;
        for(int i=left,i<=right;i++){
         sum=Math.max(sum,nums[i]+dfs(left,i-1)+dfs(i+1,right));
     }
        //coach赋值
        return sum;
    }

题目

  • 取后无影响

241. 为运算表达式设计优先级 用list代替第三维

486. 预测赢家 跟首尾取牌的某题有点像,但是是两个人的取值,并且只能取首尾(如果不是限定取首尾则是全排列),因此用区间DP,并且同2267,采用的是相对分数

877. 石子游戏 同486

894. 所有可能的满二叉树 树状区间DP

1444. 切披萨的方案数(表面上是二维,实质上还是一维)

面试题 08.14. 布尔运算

  • 取后有影响

312. 戳气球 戳气球的构造方法比较有意思,因为戳后有影响,它不是自底向上一个个戳的,而是自底向上一个个添加的

546. 移除盒子 这种是一系列题目,都是连成排的,并且取后有影响的,因此第三位是j后面有多少个相同的,还有个点是k和r的变化与coach的关系

664. 奇怪的打印机 同546,需要思考的一点是,改变颜色跟直接消除是等价的