【重点】【DFS】剑指offer——面试题67——机器人的运动范围

本文介绍了一种使用回溯法解决特定迷宫问题的方法,通过递归地探索所有可能路径来寻找从起点到终点的合法路径。文章提供了两个不同实现方案的代码示例,包括如何标记已访问节点及如何计算数字之和。

力扣,这个力扣描述题目不清晰,参考《剑指offer》书
本题与66题区别在于不用回溯!即不用把走过的地方还原回来!!!每到1个点会有4个不同的机器人分别去探路,相互之间不会走重复的网点。
题目描述:
地上有一个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。请问该机器人能够到达多少个格子?

Python

class Solution:
    def wardrobeFinishing(self, m: int, n: int, cnt: int) -> int:
        grid = [[0] * n for _ in range(m)]
        visited = [[0] * n for _ in range(m)] # 不能直接grid.copy(), 浅层复制
        for i in range(m):
            for j in range(n):
                grid[i][j] = self.digit(i) + self.digit(j)
        res = self.dfs(grid, 0, 0, m, n, cnt, visited)

        return res

    def dfs(self, grid, i, j, m, n, cnt, visited):
        if i < 0 or i >= m or j < 0 or j >= n or grid[i][j] > cnt or visited[i][j]:
            return 0
        visited[i][j] = 1
        # 不用回溯的原因是每个格子只用走1遍即可, 没有再次走的可能
        return (1 + self.dfs(grid, i-1, j, m, n, cnt, visited) 
                + self.dfs(grid, i+1, j, m, n, cnt, visited) 
                + self.dfs(grid, i, j-1, m, n, cnt, visited)
                + self.dfs(grid, i, j+1, m, n, cnt, visited))

    def digit(self, x):
        res = 0
        while x > 0:
            res += x % 10
            x = x // 10
        return res

Java

class Solution {
    public int wardrobeFinishing(int m, int n, int cnt) {
        int[][] used = new int[m][n];
        return dfs(m, n, cnt, 0, 0, used);
    }

    public int dfs(int m, int n, int cnt, int i, int j, int[][] used) {
        int count = 0;
        if (i < 0 || i >= m 
                || j < 0 || j >= n 
                || used[i][j] == 1
                || digit(i) + digit(j) > cnt) {
            return 0;
        }
        used[i][j] = 1;
        count = 1 + dfs(m, n, cnt, i - 1, j, used) 
                    + dfs(m, n, cnt, i + 1, j, used) 
                    + dfs(m, n, cnt, i, j - 1, used)
                    + dfs(m, n, cnt, i, j + 1, used);
        return count;
    }

    public int digit(int x) {
        int res = 0;
        while (x > 0) {
            res += x % 10;
            x /= 10;
        }

        return res;
    }
}

##Solution1:
此题和66题均是典型的回溯法题目,对比记忆思路!

class Solution {
public:
    int movingCount(int threshold, int rows, int cols) { 
        bool *visited = new bool[rows * cols];
        memset(visited, 0, rows * cols);
        int count = movingCountCore(threshold, rows, cols, 0, 0, visited);
        delete []visited;
        return count;
    }
    
    int movingCountCore(int threshold, int rows, int cols, int row, int col, bool *visited) {
        int count = 0;
        if(row >= 0 && row < rows && col >= 0 && col <cols
          && getDigitSum(row) + getDigitSum(col) <= threshold 
          && !visited[row * cols + col]) {
            visited[row * cols + col] = true;
            count = 1 + movingCountCore(threshold, rows, cols, row - 1, col, visited)
                + movingCountCore(threshold, rows, cols, row + 1, col, visited)
                + movingCountCore(threshold, rows, cols, row, col - 1, visited)
                + movingCountCore(threshold, rows, cols, row, col + 1, visited);
        }
        return count;
    }
    
    int getDigitSum(int n) {
        int result = 0;
        while(n != 0) {
            result += n%10;
            n /= 10;
        }
        return result;
    }
};
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值