Sword13——机器人的运动范围

Sword13——机器人的运动范围

方法1——DFS

  • 思路:从第一个单元格开始一直向下搜索,并统计个数,当无法继续执行时,则进行回溯并剪枝,重新开始另一条新路径,直到最后所有可达路径均已遍历,返回结果即可
  • 特殊情况与临界分析:k等于0时,直接返回1即可,也可包含在DFS中
  • 终止条件:每当碰到比k还要大的单元格时,即向上回溯剪枝
  • 步骤:
    • 定义一个全局辅助矩阵,用于记录矩阵中单元格已被访问
    • 将坐标m和n、以及数字k提升作用域至全局,便于DFS中使用
    • 进行相关全局变量的赋值
    • 开始递归,并返回统计结果
    • 递归方法
      • 参数:当前单元格的坐标i和j
      • 当单元格不符合规则时,直接退出
        • 单元格越界、已经被访问过、当前值总和大于k
      • 符合规则时,将辅助矩阵中设置为可行true
      • 递归对右边和下面的两个单元格进行判断,结果要加上自身符合的1
    • 计算单个数的总和方法
      • 定义结果总和
      • while循环
        • 对10不断求余数
        • 将结果加上余数
        • val不断缩小十倍
      • 返回结果即可
	// 全局辅助矩阵
	boolean[][] vistied;
	// 全局m、n、k
	int m, n, k;
	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);
    }
	// DFS方法
	private int dfs(int i, int j) {
        // 判断单元格不符合的情况
        if (i >= m || j >= n || visited[i][j] || get(i) + get(j) > k) {
            return 0;
        }
        // 符合规则,将矩阵中设置为true
        visited[i][j] = true;
        // 递归对右边和下面的单元格进行判断
        return 1 + dfs(i, j + 1) + dfs(i + 1, j);
    }
	// 计算单个数的总和
	private int get(int val) {
        // 定义总数和
        int res = 0;
        // 当val不为0,对其不断求余
        while (val != 0) {
            // res加上余数
            res += val % 10;
            // val不断缩小十倍
            val /= 10;
        }
        // 返回总和
        return res;
    }

方法1——DFS

方法2——BFS

  • 思路:广度优先遍历,一般涉及到队列,将遍历到的可行单元格依次入队,从中每弹出一个,对其右边和下面分析是否可行,可行则入队,之后重复操作即可
  • 特殊情况与临界分析:k等于0时,直接返回1即可
  • 终止条件:队列为空时,证明已获取所有可达单元格
  • 步骤:
    • k等于0的特殊情况
    • 定义辅助队列,其中存放的是每一个单元格坐标int[]
    • 向辅助队列中加入第一个单元格,确保队列非空
    • 定义辅助矩阵,用于记录被访问过的位置
    • 队列中入队元素位置,在辅助队列中设置为true
    • 定义右移或下移的节点,便于将其加入
    • 定义可达节点的结果数量
    • 循环条件:队列非空
    • while循环
      • 从队列中弹出一个单元格
      • 得出此节点的x、y坐标
      • for循环计算两次,对其右、下坐标节点判断是否符合条件
        • 根据右移或下移情况,得出下一个坐标(利用到定义的右移或下移节点
        • 判断单元格不符合规则的情况
          • 单元格越界、已经被访问过、当前值总和大于k
        • 符合规则,将其入队
        • 将对应位置的辅助矩阵处设置为true
        • 将结果值进行加1
    • 返回结果值
    • 计算单个数的总和方法
      • 定义结果总和
      • while循环
        • 对10不断求余数
        • 将结果加上余数
        • val不断缩小十倍
	public int movingCount(int m, int n, int k) {
        // k等于0时,直接返回1
        if (k == 0) return 1;
        // 定义辅助队列
        Queue<int[]> queue = new LinkedList<>();
        // 向辅助队列中加入第一个单元格,确保队列非空
        queue.offer(new int[]{0, 0});
        // 定义辅助矩阵
        boolean[][] visited = new boolean[m][n];
        // 将入队过的第一个单元格,在辅助矩阵中设置为true
        visited[0][0] = true;
        // 定义坐标右移和下移的坐标
        int[] dx = {0, 1};
        int[] dy = {1, 0};
        // 定义可达坐标的数量
        int res = 1;
        // while循环
        while (!queue.isEmpty()) {
            // 弹出一个单元格
            int[] cell = queue.poll();
            // 获取单元格的x、y坐标
            int x = cell[0], y = cell[1];
            // for循环执行两次,判断右、下坐标是否满足条件
            for (int i = 0; i < 2; i++) {
                // 根据右移或下移情况,得出下一个坐标
                int nx = x + dx[i], ny = y + dy[i];
                // 判断单元格不符合符合规则的情况
                if (nx >= m || ny >= n || visited[nx][ny] || get(nx) + get(ny) > k) {
                    continue;
                }
                // 将当前坐标入队
                queue.offer(new int[]{nx, ny});
                // 将辅助矩阵处设置为true
                visited[nx][ny] = true;
                // 将结果值加1
                res++;
            }
        }
        // 返回结果
        return res;
    }
	// 计算单个数的总和
	private int get(int val) {
        // 定义总数和
        int res = 0;
        // 当val不为0,对其不断求余
        while (val != 0) {
            // res加上余数
            res += val % 10;
            // val不断缩小十倍
            val /= 10;
        }
        // 返回总和
        return res;
    }

方法2——BFS

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值