机器人的运动范围

机器人的运动范围

http://www.nowcoder.com/questionTerminal/6e5207314b5241fb83f2329e89fdecc8

描述

这是一篇针对初学者的题解。共用两种方法解决,
知识点:DFS,BFS
难度:二星


题解

题目描述:给定一个矩阵的行和列row,col和阈值sho,从(0,0)出发,每次可以往上下左右四个方向走,并且走到(i,j)时,i和j的每位数之和需要小于等于sho,问最多可以走多少格子。

方法一:DFS遍历

根据题目描述,我们可以模拟题目,我们假设一个5x5矩阵,阈值sho=3,如果我们用DFS的话,就相当于“不撞南墙不回头”,我在下面画了一个图,
![ ](https://uploadfiles.nowcoder.com/images/20200519/284295_1589877614926_ABC6FAAB5BAD4415E420440E8397D9B9 "图片标题")
最开始,我们在(0,0)的位置,我们假设按照{右,下,左,上}的方向去试探。所以我们走的顺序应该是按照图中的下标走的。
当走到4的时候,发现不能往继续往右边走,并且4个方向都走不通了,那就回溯到3,发现可以走到5,接着就站在5的视角,发现可以走6,就一直按照这个想法。

本题的递归函数就是:首先站在(0,0)的视角,先往右试探,发现可以走,就以下一个为视角,继续做相同的事情。
递归函数模板为:

dfs(){

    // 第一步,检查下标

    // 第二步:检查是否被访问过,或者是否满足当前匹配条件

    // 第三步:检查是否满足返回结果条件

    // 第四步:都没有返回,说明应该进行下一步递归
    // 标记
    dfs(下一次)
    // 回溯
}  
int main() {
    dfs(0, 0);
}

按照模板改写代码:

class Solution {

public:
    using V = vector<int>;
    using VV = vector<V>;    
    int dir[5] = {-1, 0, 1, 0, -1};

    int check(int n) {
        int sum = 0;

        while (n) {
            sum += (n % 10);
            n /= 10;
        }

        return sum;
    }

    void dfs(int x, int y, int sho, int r, int c, int &ret, VV &mark) {
        // 检查下标 和 是否访问
        if (x < 0 || x >= r || y < 0 || y >= c || mark[x][y] == 1) {
            return;
        }
        // 检查当前坐标是否满足条件
        if (check(x) + check(y) > sho) {
            return;
        }
        // 代码走到这里,说明当前坐标符合条件
        mark[x][y] = 1;
        ret += 1;

        for (int i = 0; i < 4; ++i) {
            dfs(x + dir[i], y + dir[i + 1], sho, r, c, ret, mark);
        }



    } 
    int movingCount(int sho, int rows, int cols)
    {
        if (sho <= 0) {
            return 0;
        }

        VV mark(rows, V(cols, -1));
        int ret = 0;
        dfs(0, 0, sho, rows, cols, ret, mark);
        return ret;
    }
};

时间复杂度:O(mn), m,n为矩阵大小,每个元素最多访问过一次
空间复杂度:O(m
n)

方法二:BFS遍历

当前图的遍历算法还有bBFS,所以也可以用BFS做。方法一实例的图,用BFS就是如下这样:
![图片说明](https://uploadfiles.nowcoder.com/images/20200519/284295_1589878467112_921F1E74912BCD2AD922A5DEFC42ED71 "图片标题")

代码如下:

class Solution {
public:
    using pii = pair<int,int>;
    int dir[5] = {-1, 0, 1, 0, -1};
    int check(int n) {
        int sum = 0;

        while (n) {
            sum += (n % 10);
            n /= 10;
        }

        return sum;
    }
    int movingCount(int sho, int rows, int cols)
    {
        if (sho <= 0) {
            return 0;
        }

        int ret = 0;
        int mark[rows][cols];
        memset(mark, -1, sizeof(mark));
        queue<pii> q;
        q.push({0, 0});
        mark[0][0] = 1;


        while (!q.empty()) {
            auto node = q.front();
            q.pop();
            // 每次保证进队列的都是满足条件的坐标
            ++ret;

            for (int i = 0; i < 4; ++i) {
                int x = node.first + dir[i];
                int y = node.second + dir[i + 1];

                if (x >= 0 && x < rows && y >= 0 && y < cols && mark[x][y] == -1) {
                    if (check(x) + check(y) <= sho) {
                        q.push({x, y});
                        mark[x][y] = 1;
                    }
                }
            }
        }

        return ret;
    }
};

时间复杂度:O(mn), m,n为矩阵大小,每个元素最多访问过一次
空间复杂度:O(m
n)

全部评论

相关推荐

点赞 评论 收藏
转发
点赞 收藏 评论
分享
牛客网
牛客企业服务