机器人活动区域

一、题目描述

现有一个机器人,可放置于 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;  // 返回当前区域的大小
    }
}
相关推荐
MarkHD1 小时前
车辆TBOX科普 第53次 三位一体智能车辆监控:电子围栏算法、驾驶行为分析与故障诊断逻辑深度解析
算法
a3158238061 小时前
Android Framework开发知识点整理
android·java·linux·服务器·framework·android源码开发
苏小瀚1 小时前
[算法]---路径问题
数据结构·算法·leetcode
毕设源码-朱学姐2 小时前
【开题答辩全过程】以 个人健康管理系统为例,包含答辩的问题和答案
java·spring boot
局外人Inside2 小时前
PostProcessingBeanDeserializer 使用指南
java
郑州光合科技余经理2 小时前
基于PHP:海外版同城O2O系统多语言源码解决方案
java·开发语言·git·spring cloud·uni-app·php·uniapp
lqj_本人2 小时前
Flutter 适配鸿蒙桌面快捷入口完整指南
flutter·华为·harmonyos
月明长歌2 小时前
【码道初阶】一道经典简单题:多数元素(LeetCode 169)|Boyer-Moore 投票算法详解
算法·leetcode·职场和发展
IT_Octopus2 小时前
Java GZip 压缩实践 +实践思考 +进一步压榨性能和存储方案思考:Protobuf+ GZip
java·spring boot