机器人活动区域

一、题目描述

现有一个机器人,可放置于 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. 输入读取与初始化:

    • 读取矩阵尺寸 m、n 和矩阵 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;  // 返回当前区域的大小
    }
}
相关推荐
靠沿1 分钟前
MySQL数据库基础——事务
java·数据库·mysql
蒲公英eric3 分钟前
线性回归与正则化:从最小二乘到岭回归、LASSO
人工智能·算法·数学建模·线性回归·岭回归·最小二乘·lasso
碧海银沙音频科技研究院4 小时前
炬芯ATS3089X手表的HFP通话不自动路由到设备BT的问题解决
网络·人工智能·嵌入式硬件·算法
Joy T6 小时前
Agent 确定性上下文设计:从 Prompt 参数注入到能力分层
java·开发语言·微服务·架构·prompt·agent context
m0_587383009 小时前
广州 24 小时自助健身房解决方案技术实现与实战指南
java·spring·小程序·架构·需求分析
mmmmath_39 小时前
LeetCode.199.二叉树的右视图
数据结构·leetcode
·云扬·9 小时前
Prompt 工程与安全:从 System 设计到注入防御
java·人工智能·安全·ai·prompt
专注仿真9 小时前
引擎扩展性与集成设计深度剖析:从 14 个扩展点到 DIS→HLA 演进之路
开发语言·算法·仿真引擎·推演引擎
码爸9 小时前
支持向量机介绍与示例
算法·机器学习·支持向量机