剑指 Offer 13. 机器人的运动范围

题目描述

地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。例如,当k为18时,机器人能够进入方格 [35, 37] ,因为3+5+3+7=18。但它不能进入方格 [35, 38],因为3+5+3+8=19。请问该机器人能够到达多少个格子?

解题思路

方法一:广度优先

首先需要一个函数得到某个位置的下标有多少位:

cpp 复制代码
int Solution::get(int x)
{
    int res = 0;
    for (; x; x /= 10)
        res += x % 10;
    return res;
}

通过上面的函数得到某个位置横坐标和纵坐标的位数,来和k比较是否满足题目要求。

广度优先采用队列的方式解决,用一个队列存储满足条件的位置,由于是从左上角(0,0)开始,因此只需要看它的右边和下边即可。将满足条件的点加入到队列中作为下一次需要被查询右边和下边的点。另外用一个二维数组标记已经被访问过的位置,因为向下和向右查找时包含被查询过的点。

当出现x<0或者y<0或者x>=m或者y<=n或者坐标位数和大于k时则跳过该点。

方法二:深度优先

深度优先则需要使用递归。首先需要搞清楚递归返回的条件。什么时候递归返回?当当前访问的横坐标或纵坐标>=m,n的值或者横坐标位数+纵坐标位数>k或者当前节点已经被访问过了(由于是向右和向下两个方向,因此不会出现i/j<0),此时返回0。(返回0而不是false是因为我们需要得到能到达的个数)

在深度优先中涉及到一个-8的操作,这里举例说明:

例如我们现在的i是19,下一次+1则为20,而19对应的位数和是10;但20对应的位数和是2。

代码

方法一:

cpp 复制代码
int Solution::get(int x)
{
    int res = 0;
    for (; x; x /= 10)
        res += x % 10;
    return res;
}

int Solution::movingCount(int m, int n, int k)
{
    if (!k) 
        return 1;

    std::queue<std::pair<int, int> > Q;
    int dx[2] = { 0, 1 };
    int dy[2] = { 1, 0 };
    std::vector<std::vector<int> > vis(m, std::vector<int>(n, 0));

    Q.push(std::make_pair(0, 0));
    vis[0][0] = 1;
    int ans = 1;

    while (!Q.empty()) {
        int x, y;
        std::tie(x, y) = Q.front();
        Q.pop();
        for (int i = 0; i < 2; ++i) {
            int tx = dx[i] + x;
            int ty = dy[i] + y;
            if (tx < 0 || tx >= m || ty < 0 || ty >= n || vis[tx][ty] || get(tx) + get(ty) > k) 
                continue;
            Q.push(std::make_pair(tx, ty));
            vis[tx][ty] = 1;
            ans++;
        }
    }
    return ans;
}

方法二:

cpp 复制代码
class Solution {
public:
    int movingCount(int m, int n, int k) {
        vector<vector<bool>> visited(m, vector<bool>(n, false));
        return dfs(0, 0, k, visited);
    }

private:
    int dfs(int i, int j, int k, vector<vector<bool>>& visited) {
        if (i >= visited.size() || j >= visited[0].size() || visited[i][j] || getSum(i, j) > k) {
            return 0;
        }

        visited[i][j] = true;

        return 1 + dfs(i + 1, j, k, visited) + dfs(i, j + 1, k, visited);
    }

    int getSum(int i, int j) {
        int sum = 0;
        while (i > 0) {
            sum += i % 10;
            i /= 10;
        }
        while (j > 0) {
            sum += j % 10;
            j /= 10;
        }
        return sum;
    }
};
相关推荐
晓星航1 小时前
Docker本地部署Chatbot Ollama搭建AI聊天机器人并实现远程交互
人工智能·docker·机器人
忍界英雄1 小时前
LeetCode:2398. 预算内的最多机器人数目 双指针+单调队列,时间复杂度O(n)
算法·leetcode·机器人
Tisfy2 小时前
LeetCode 2398.预算内的最多机器人数目:滑动窗口+单调队列——思路清晰的一篇题解
算法·leetcode·机器人·题解·滑动窗口
北京搜维尔科技有限公司8 小时前
搜维尔科技:OptiTrack将捕捉到的人类动作数据映射到人形机器人的各个关节上进行遥操作
科技·机器人
King's King8 小时前
6年前倒闭的机器人独角兽,再次杀入AGV市场
机器人
孔武10 小时前
SG-SLAM下载部署安装运行记录
机器人·自动驾驶
云卓科技16 小时前
无人机之控制距离篇
科技·安全·机器人·无人机·制造
云卓科技16 小时前
无人机之飞行高度篇
科技·安全·机器人·无人机·制造
Java追光着1 天前
扣子智能体实战-汽车客服对话机器人(核心知识:知识库和卡片)
人工智能·机器人·汽车·智能体
夜幕龙1 天前
robomimic基础教程(三)——自带算法
人工智能·python·算法·机器人