机器人的运动范围(数位和、可达解、深度优先遍历、广度优先遍历)

本文介绍了一种从坐标(0,0)出发,在二维网格中寻找所有可能路径的方法,路径上的每个点的数位和需小于给定阈值。文章详细解释了数位和的计算方法,并提供了两种解决方案:深度优先搜索(DFS)与广度优先搜索(BFS),适用于算法与数据结构的学习。

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

题目要求从0,0开始移动,每次移动的格位要求数位和相加小于阈值。

首先数位和的求法:

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

利用取余和除法达到目的。

另一种:
因为该题是从0,0开始递增的,并不需要突兀的求某个大值的数位和,那么就可以通过找到相邻数字数位和的规律来求出。

(i + 1) % 10 != 0 ? si + 1 : si - 8

当前一个数加一取余10等于0,例如:
5和6
6的数位和相比于5直接加一即可
18和19
数位和:9和10

当前一个数加一取余10不为0,例如:
19和20
数位和10和2
29和30
数位和11和3
可以看出后者数位和是前者-8的结果。
实际数位和在此处发生突变是因为后者的9变为0,高位加一故最终结果-8即可。也看出这个计算只能用于两位计算。

可达解:
对于该题,矩阵中共有三种情况,可达解、不可达解、非解
二维矩阵下标是对称分布的,那么其可达解的分布也应是对称的,呈自左上向右下的等腰三角形分布,又因为数位和的突变特性,一个矩形中往往有多个符合解的等腰三角形,但有些解不可达,如图:
在这里插入图片描述
借用力扣上大神的图片。
蓝色块为可达解,红色是不满足数位和要求的非解,黄色就是不可达解,但当k值持续增大,蓝色区域与黄色区域连接起来,导致不可达解变为可达解。
如图:
在这里插入图片描述
因为可达解与不可达解的交界永远位于右侧或下侧,那么在遍历时候,只需要对节点持续的向右或向下遍历即可遍历出所有的节点。

深度优先遍历DFS:
对矩阵遍历时,先由节点持续向下遍历,当无法继续向下,再向右遍历,当下右都不可以,回溯到前一个节点进行右遍历。

	int m, n, k;
    boolean[][] visited;
    public int movingCount1(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]) {
            return 0;
        }

        visited[i][j] = true;

        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);
    }

广度优先遍历BFS:
该遍历利用队列,把节点加入队列后,取出节点,判断后将其下、右节点都放入队列以供后面使用。

public int movingCount2(int m, int n, int k) {
        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
发出的红包

打赏作者

魔幻音

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值