剑指 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;
    }
};
相关推荐
Lu_ffy-6 小时前
如何创建你的第一个 Telegram 机器人:一步步教程
机器人
EAI-Robotics9 小时前
机器人打包物品研究现状简述
机器人
肥猪猪爸9 小时前
使用卡尔曼滤波器估计pybullet中的机器人位置
数据结构·人工智能·python·算法·机器人·卡尔曼滤波·pybullet
清安无别事13 小时前
闲聊?泳池清洁机器人?
机器人
zhd15306915625ff13 小时前
库卡机器人维护需要注意哪些事项
安全·机器人·自动化
宋1381027972017 小时前
Manus Xsens Metagloves虚拟现实手套
人工智能·机器人·vr·动作捕捉
禁默18 小时前
第六届机器人、智能控制与人工智能国际学术会议(RICAI 2024)
人工智能·机器人·智能控制
Robot2511 天前
Figure 02迎重大升级!!人形机器人独角兽[Figure AI]商业化加速
人工智能·机器人·微信公众平台
FreeIPCC1 天前
谈一下开源生态对 AI人工智能大模型的促进作用
大数据·人工智能·机器人·开源
施努卡机器视觉2 天前
电解车间铜业机器人剥片技术是现代铜冶炼过程中自动化和智能化的重要体现
运维·机器人·自动化