leetcode 2435

2435: 矩阵中和能被K整除的路径

返回答案对 109 + 7 取余 的结果

复制代码
constexpr int MOD=1'000'000'007;

思路:动态规划------从记忆化搜索到递推

本题需要统计路径和是 k 的倍数的路径数目。

加法原理:如果完成一件事有若干互不重叠、互不干扰的办法,那么总方法数 = 每类办法数之和。

递归边界:dfs(−1,j,s)=dfs(i,−1,s)=0 无法从 (0,0) 到达这些位置。

dfs(0,0,grid[0][0]modk)=1 起点到它自己有一条路径,即原地不动。

递归入口:题目求从起点 (0,0) 走到 (m−1,n−1),且路径和模 k 为 0 的路径数,即dfs(m−1,n−1,0)

复制代码
vector memo(m, vector(n, vector<int>(k, -1)));
复制代码
auto dfs = [&](this auto&& dfs, int i, int j, int s) -> int

-> int尾置返回类型(trailing return type) 语法,它明确告诉编译器:这个 lambda 调用后的返回值是 int 类型。

复制代码
class Solution {
public:
    int numberOfPaths(vector<vector<int>>& grid, int k) {
        constexpr int MOD=1'000'000'007;
        int m=grid.size(),n=grid[0].size();
        vector memo(m,vector(n,vector<int>(k,-1)));  //初始化为-1,表示未遇到过

        auto dfs=[&](this auto&& dfs,int i,int j,int s)->int{
            if(i<0 || j<0) return 0; //出界
            int pre_s=((s-grid[i][j])%k+k)%k;
            if(i==0 && j==0){
                return pre_s==0; //是否能回到起点
            }
            int &res=memo[i][j][s];  //引用
            if(res!=-1) return res; //遇到过
            return res=(dfs(i-1,j,pre_s)+dfs(i,j-1,pre_s))%MOD;
        };

        return dfs(m-1,n-1,0);
    }
};

进一步,1:1 翻译成递推。

递归边界:

  • dfs(−1,0,0)=1。为方便翻译成递推,把 (−1,0) 视作一个合法的位置。从终点 (m−1,n−1) 走到 (−1,0) 时,如果路径和 s 是 k 的倍数,则找到了一条合法路径。
  • dfs(−1,j,s)=dfs(i,−1,s)=0。除了 (−1,0),其余出界位置视作非法。

也可以把 f[0][1] 初始化成 1,这样我们无需单独计算 f[1][1]。从 dfs 的角度理解,就是++把 (−1,0) 当作起点,且第一步只能往下走。++

注:如果不写 f[0][1]=1,那么需要在代码中特判 i=j=0 的情况,因为 f[1][1] 属于初始值,不能用状态转移方程计算。但是,如果把初始值改成 f[0][1]=1(或者 f[1][0]=1),就无需特判 i=j=0 的情况了,f[1][1] 也可以用状态转移方程计算。

复制代码
class Solution {
public:
    int numberOfPaths(vector<vector<int>>& grid, int k) {
        constexpr int MOD=1'000'000'007;
        int m=grid.size(),n=grid[0].size();
        vector f(m+1,vector(n+1,vector<int>(k)));
        f[0][1][0]=1;  //把 (−1,0) 当作起点,且第一步只能往下走
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                for(int s=0;s<k;s++){
                    int preS=((s-grid[i][j])%k+k)%k;
                    f[i+1][j+1][s]=(f[i][j+1][preS]+f[i+1][j][preS])%MOD;
                }
            }
        }

        return f[m][n][0];
    }
};
相关推荐
智者知已应修善业几秒前
【51单片机1,左边4个LED灯先闪烁2次后,右边4个LED灯再闪烁2次:2,接着所用灯一起闪烁3次,接着重复步骤1,如此循环。】2023-5-19
c++·经验分享·笔记·算法·51单片机
米啦啦.几秒前
红黑树,,
数据结构·红黑树
xiaoye-duck6 分钟前
《算法题讲解指南:优选算法-队列+宽搜》--70.N叉树的层序遍历,71.二叉树的锯齿形层序遍历,72.二叉树的最大宽度,73.在每个树行中找最大值
数据结构·c++·算法·队列
汀、人工智能8 分钟前
[特殊字符] 第98课:数据流中位数
数据结构·算法·数据库架构··数据流·数据流中位数
Eloudy11 分钟前
不同特征值的特征向量互相正交的矩阵
人工智能·算法·机器学习
人道领域14 分钟前
【LeetCode刷题日记】:从 LeetCode 经典题看哈希表的场景化应用---数组、HashSet、HashMap 选型与算法实战
算法·leetcode·面试
努力努力再努力wz14 分钟前
【C++高阶系列】告别内查找局限:基于磁盘 I/O 视角的 B 树深度剖析与 C++ 泛型实现!(附B树实现源码)
java·linux·开发语言·数据结构·c++·b树·算法
承渊政道15 分钟前
【优选算法】(实战攻坚BFS之FloodFill、最短路径问题、多源BFS以及解决拓扑排序)
数据结构·c++·笔记·学习·算法·leetcode·宽度优先
kishu_iOS&AI16 分钟前
机器学习 —— 线性回归(2)
人工智能·python·算法·机器学习·线性回归
NULL指向我19 分钟前
信号处理学习笔记6:ADC采样线性处理实测拟合
人工智能·算法·机器学习