机器人活动区域

一、题目描述

现有一个机器人,可放置于 M × N 的网格中任意位置,每个网格包含一个非负整数编号,当相邻网格的数字编号差值的绝对值小于等于 1 时,机器人可以在网格间移动。

问题: 求机器人可活动的最大范围对应的网格点数目。​

说明:​网格左上角坐标为 (0,0) ,右下角坐标为(m−1,n−1) ,机器人只能在相邻网格间上下左右移动。

二、输入输出描述

1. 输入描述

  • 第一行:两个整数 M 和 N ,M 表示网格的行数 N 表示网格的列数,1 ≤ M,N ≤ 150;
  • 后续 M 行:每行 N 个数值(数值大小用 k 表示, 0 ≤ k ≤ 50),数值间用单个空格分隔。

2. 输出描述

  • 输出一个整数,表示机器人可活动的最大区域的网格点数目。

三、示例

|----|-------------------------------------|
| 输入 | 4 4 1 2 5 2 2 4 4 5 3 5 7 1 4 6 2 4 |
| 输出 | 6 |
| 说明 | |

四、解题思路

1. 核心思想

通过广度优先搜索(BFS) 遍历矩阵中所有未访问的单元格,逐个计算其所在连通区域的大小,最终筛选出最大的区域大小 ------ 核心是 "遍历不重复 + 连通性判定 + 大小统计"。

2. 问题本质分析

问题本质是带条件的连通区域查找与大小统计

  • 连通性规则:单元格仅与 "上下左右相邻 + 数值差值≤1" 的单元格连通(非传统的 "数值相同" 连通,而是差值范围放宽到≤1)。
  • 目标:找到所有满足该连通规则的区域中,包含单元格数量最多的那个,输出其数量。
  • 关键约束:需避免重复遍历(同一单元格只能属于一个连通区域),因此需要访问标记数组。
3. 核心逻辑
  • 遍历全覆盖:逐行逐列遍历矩阵所有单元格,确保每个未访问的单元格都能触发一次 BFS,覆盖所有连通区域。
  • BFS 连通性判定:以队列作为核心数据结构,逐层扩展相邻单元格,仅纳入满足 "范围 + 访问 + 差值" 条件的单元格,统计区域大小。
  • 最大值更新:每次 BFS 计算出一个区域的大小后,与当前最大值对比,保留更大值。
4. 步骤拆解
  1. 输入读取与初始化

    • 读取矩阵尺寸 mn 和矩阵 grid
    • 初始化访问标记数组 visited(全为 false)、最大区域大小 maxSize(初始 0)、方向偏移量 dirs
  2. 遍历矩阵,触发 BFS

    • 循环遍历矩阵的每个单元格 (i,j)
      • visited[i][j] == false(未被访问),调用 BFS 计算该单元格所在连通区域的大小。
      • 用 BFS 返回的区域大小更新 maxSize(取最大值)。
  3. BFS 计算连通区域大小

    • 初始化队列,加入起始单元格 (x,y),标记为已访问,区域大小初始化为 1。
    • 队列非空时,弹出头部单元格,遍历其四个方向的相邻单元格:
      • 筛选符合条件的相邻单元格(范围合法 + 未访问 + 数值差值≤1)。
      • 满足条件则标记访问、加入队列、区域大小 + 1。
    • 队列遍历完成后,返回当前区域大小。
  4. 结果输出

    • 遍历完所有单元格后,返回并输出 maxSize(最大连通区域的大小)。

五、代码实现

java 复制代码
import java.util.*;
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        // 读取矩阵的行数和列数
        int m = sc.nextInt();
        int n = sc.nextInt();
        // 读取矩阵内容
        int[][] grid = new int[m][n];
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                grid[i][j] = sc.nextInt();
            }
        }
        // 输出最大区域的大小
        System.out.println(getResult(grid, m, n));
    }
    // 计算矩阵中最大的连通区域的大小
    public static int getResult(int[][] grid, int m, int n) {
        boolean[][] visited = new boolean[m][n]; // 访问标记数组
        int maxSize = 0;  // 记录最大的区域大小
        // 四个方向的偏移量,上下左右
        int[][] dirs = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
        // 遍历整个矩阵
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                // 如果当前点没有被访问过,执行 BFS 计算该区域的大小
                if (!visited[i][j]) {
                    int size = bfs(grid, visited, i, j, m, n, dirs);
                    // 更新最大区域的大小
                    maxSize = Math.max(maxSize, size);
                }
            }
        }
        return maxSize;  // 返回最大的区域大小
    }
    // 使用 BFS 查找从 (x, y) 出发的连通区域的大小
    private static int bfs(int[][] grid, boolean[][] visited, int x, int y, int m, int n, int[][] dirs) {
        Queue<int[]> queue = new LinkedList<>();  // BFS 使用的队列
        queue.offer(new int[]{x, y});  // 将起始点加入队列
        visited[x][y] = true;  // 标记起始点为已访问
        int size = 1;  // 当前区域的大小,从起始点开始
        // 当队列不为空时,继续遍历
        while (!queue.isEmpty()) {
            int[] point = queue.poll();  // 弹出队列中的一个元素
            // 遍历当前点的四个方向
            for (int[] dir : dirs) {
                int newX = point[0] + dir[0];  // 计算新点的横坐标
                int newY = point[1] + dir[1];  // 计算新点的纵坐标
                // 确保新点在矩阵范围内,并且未被访问过
                // 同时新点与当前点的差值小于等于 1,才将新点加入队列
                if (newX >= 0 && newX < m && newY >= 0 && newY < n && !visited[newX][newY]
                        && Math.abs(grid[point[0]][point[1]] - grid[newX][newY]) <= 1) {
                    visited[newX][newY] = true;  // 标记新点为已访问
                    queue.offer(new int[]{newX, newY});  // 将新点加入队列
                    size++;  // 增加当前区域的大小
                }
            }
        }
        return size;  // 返回当前区域的大小
    }
}
相关推荐
qq_4308558817 小时前
线代第二章矩阵第五、六、七节矩阵的转置、方阵的行列式、方阵的伴随矩阵
线性代数·算法·矩阵
不急不躁12317 小时前
Android16 给应用默认获取权限
android·java
jianfeng_zhu17 小时前
二叉树的中序线索化,并通过线索化后遍历二叉树
数据结构·链表
C雨后彩虹17 小时前
5G网络建设
java·数据结构·算法·华为·面试
机器学习之心17 小时前
最小二乘支持向量机(LSSVM)结合遗传算法(GA)解决单目标优化问题,MATLAB代码
算法·支持向量机·matlab·单目标优化问题
码界奇点17 小时前
基于Spring Boot的后台管理系统设计与实现
java·spring boot·后端·车载系统·毕业设计·源代码管理
爱敲点代码的小哥17 小时前
json序列化和反序列化 和 数组转成json格式
java·前端·json
零度念者17 小时前
Java IO/NIO 深度解析:从底层原理到高性能图片网关实战
java·nio
没有故事的Zhang同学17 小时前
09-🔍数据结构与算法核心知识 | 二叉搜索树:有序数据结构理论与实践
算法