剑指--机器人的运动范围

本文详细解析了机器人的运动范围问题,通过深度优先遍历(DFS)和广度优先遍历(BFS)两种算法,探讨了如何在给定矩阵中,基于数位和不超过k的条件下,计算机器人可以到达的所有位置数量。提供了具体实现代码,帮助读者理解并掌握算法细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

剑指–机器人的运动范围

1,题目:

在这里插入图片描述
2,思路:

深度优先遍历 DFS

算法解析:

  • 1.递归参数: 当前元素在矩阵中的行列索引 i 和 j ,两者的数位和 si, sj 。
  • 2.终止条件: 当 ① 行列索引越界 或 ② 数位和超出目标值 k 或 ③ 当前元素已访问过 时,返回 0 ,代表不计入可达解。
  • 3.递推工作:
  • 4.标记当前单元格 :将索引 (i, j) 存入 visited 中,代表此单元格已被访问过。
  • 5.搜索下一单元格: 计算当前元素的 下、右 两个方向元素的数位和,并开启下层递归 。
  • 6.回溯返回值: 返回 1 + 右方搜索的可达解总数 + 下方搜索的可达解总数,代表从本单元格递归搜索的可达解总数。

下面是对应的图解:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

方法二:广度优先:

算法解析:

  • 1.初始化: 将机器人初始点 (0, 0) 加入队列 queue ;
  • 2.迭代终止条件: queue 为空。代表已遍历完所有可达解。
  • 3.迭代工作:
  • 4.单元格出队: 将队首单元格的 索引、数位和 弹出,作为当前搜索单元格。
  • 5.判断是否跳过: 若 ① 行列索引越界 或 ② 数位和超出目标值 k 或 ③ 当前元素已访问过 时,执行 continue 。
  • 6.标记当前单元格 :将单元格索引 (i, j) 存入 visited 中,代表此单元格 已被访问过 。
  • 7.单元格入队: 将当前元素的 下方、右方 单元格的 索引、数位和 加入 queue 。
  • 8.返回值: visited 的长度 len(visited) ,即可达解的数量。

下面是对应的图解:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
3,代码:

深度优先遍历 DFS

class Solution {
    /*
    算法解析:
1.递归参数: 当前元素在矩阵中的行列索引 i 和 j ,两者的数位和 si, sj 。
2.终止条件: 当 ① 行列索引越界 或 ② 数位和超出目标值 k 或 ③ 当前元素已访问过 时,返回 0 ,代表不计入可达解。
3.递推工作:
4.标记当前单元格 :将索引 (i, j) 存入  visited 中,代表此单元格已被访问过。
5.搜索下一单元格: 计算当前元素的 下、右 两个方向元素的数位和,并开启下层递归 。
6.回溯返回值: 返回 1 + 右方搜索的可达解总数 + 下方搜索的可达解总数,代表从本单元格递归搜索的可达解总数。

    */
    int m, n, k;
    boolean[][] visited;
    public int movingCount(int m, int n, int k) {
        this.m = m; this.n = n; this.k = k;
        this.visited = new boolean[m][n];
        return dfs(0, 0, 0, 0);
    }
    public int dfs(int i, int j, int si, int sj) {
        if(i >= m || j >= n || k < si + sj || visited[i][j]) //当 ① 行列索引越界 或 ② 数位和超出目标值 k 或 ③ 当前元素已访问过 时,返回 0 ,代表不计入可达解。
            return 0;
        visited[i][j] = true;//标记当前单元格 :将索引 (i, j) 存入  visited 中,代表此单元格已被访问过。
        return 1 + dfs(i + 1, j, (i + 1) % 10 != 0 ? si + 1 : si - 8, sj) + dfs(i, j + 1, si, (j + 1) % 10 != 0 ? sj + 1 : sj - 8);//回溯返回值: 返回 1 + 右方搜索的可达解总数 + 下方搜索的可达解总数,代表从本单元格递归搜索的可达解总数。
    }
}

深度优先的另一种写法:

class Solution {

    public int movingCount(int m, int n, int k) {
        boolean[][] visited = new boolean[m][n];
        return dfs(visited, m, n, k, 0, 0);
    }

    private int dfs(boolean[][] visited, int m, int n, int k, int i, int j) {
        if(i >= m || j >= n || visited[i][j] || bitSum(i) + bitSum(j) > k) return 0;
        visited[i][j] = true;
        return 1 + dfs(visited, m, n, k, i + 1, j) + dfs(visited, m, n, k, i, j + 1) ;
    }

    private int bitSum(int n) {
        int sum = 0;
        while(n > 0) {
            sum += n % 10;
            n /= 10; 
        }
        return sum;
    }
}

方法二:广度优先:

class Solution {
    public int movingCount(int m, int n, int k) {
        /*
        方法二:广度优先遍历 BFS

算法解析:
1.初始化: 将机器人初始点 (0, 0) 加入队列 queue ;
2.迭代终止条件: queue 为空。代表已遍历完所有可达解。
3.迭代工作:
4.单元格出队: 将队首单元格的 索引、数位和 弹出,作为当前搜索单元格。
5.判断是否跳过: 若 ① 行列索引越界 或 ② 数位和超出目标值 k 或 ③ 当前元素已访问过 时,执行 continue 。
6.标记当前单元格 :将单元格索引 (i, j) 存入  visited 中,代表此单元格 已被访问过 。
7.单元格入队: 将当前元素的 下方、右方 单元格的 索引、数位和 加入 queue 。
8.返回值: visited 的长度 len(visited) ,即可达解的数量。


        */
        boolean[][] visited = new boolean[m][n];
        int res = 0;
        Queue<int[]> queue= new LinkedList<int[]>();
        queue.add(new int[] { 0, 0, 0, 0 });
        while(queue.size() > 0) {
            int[] x = queue.poll();
            int i = x[0], j = x[1], si = x[2], sj = x[3];
            if(i >= m || j >= n || k < si + sj || visited[i][j]) continue;
            visited[i][j] = true;
            res ++;
            queue.add(new int[] { i + 1, j, (i + 1) % 10 != 0 ? si + 1 : si - 8, sj });
            queue.add(new int[] { i, j + 1, si, (j + 1) % 10 != 0 ? sj + 1 : sj - 8 });
        }
        return res;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值