剑指 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;
    }
};
相关推荐
自不量力的A同学5 小时前
全球首款 5G-A 人形机器人发布
5g·机器人
十年一梦实验室10 小时前
波士顿动力ATLAS 3.0展示6项新AI升级(SPACEO机器人)
人工智能·机器人
电气_空空10 小时前
基于单片机及传感器的机器人设计与实现
单片机·嵌入式硬件·机器人·毕业设计·毕设
boss-dog10 小时前
视觉在协作机器人上的场景应用
机器人·视觉
IT猿手15 小时前
2025最新群智能优化算法:云漂移优化(Cloud Drift Optimization,CDO)算法求解23个经典函数测试集,MATLAB
开发语言·数据库·算法·数学建模·matlab·机器人
IT猿手20 小时前
2025最新群智能优化算法:海市蜃楼搜索优化(Mirage Search Optimization, MSO)算法求解23个经典函数测试集,MATLAB
开发语言·人工智能·算法·机器学习·matlab·机器人
一尘之中1 天前
从青铜巨人到硅基生命:机器人文明的意识觉醒之路--三千年人类想象与科技突破的双螺旋演进)
人工智能·科技·机器人
十年一梦实验室1 天前
机器人驱控一体平台简介
机器人
PNP机器人1 天前
研究案例:英伟达研究中心,华盛顿大学——TacSL:使用Franka机器人的视觉触觉传感器模拟和学习库
人工智能·深度学习·机器人·franka fr3
m0_665815102 天前
联核科技AGV无人叉车的应用场景有哪些?
人工智能·科技·机器人·自动化·自动驾驶