华为OD机试真题---机器人活动区域

华为OD机试中的“机器人活动区域”题目是一个典型的图论和搜索算法问题,要求在一个二维网格中找出满足特定条件的连续区域,并计算这些区域中最大的一个区域所包含的格子数。具体来说,这个问题要求机器人能够在网格中移动,其移动规则是相邻格子之间的数字编号差值的绝对值必须小于等于1。

题目描述

  • 输入:
    • 第一行包含两个整数M和N,分别表示网格的行数和列数。
    • 接下来的M行,每行包含N个整数,表示网格中每个格子的数字编号。
  • 输出:
    • 输出一个整数,表示机器人可活动的最大范围对应的网格点数目。

解题思路

  1. 遍历网格:从网格的左上角开始,逐个遍历每个格子。
  2. 深度优先搜索(DFS)或广度优先搜索(BFS)
    • 当遍历到一个格子时,检查其所有相邻的格子(上、下、左、右四个方向,也可以考虑对角线方向,但题目通常只要求四个基本方向)。
    • 如果相邻格子的数字编号与当前格子满足差值绝对值小于等于1的条件,则将该相邻格子加入到当前区域中,并继续对该相邻格子进行相同的搜索过程。
    • 使用一个标记数组来记录哪些格子已经被访问过,以避免重复访问。
  3. 计算区域大小:在搜索过程中,统计当前区域包含的格子数。
  4. 寻找最大区域:遍历完整个网格后,找到并输出所有区域中最大的一个区域所包含的格子数。

示例

示例1
  • 输入:
    4 4
    1 2 5 2
    2 4 4 5
    3 5 7 1
    
  • 输出:
    6
    
    解释:在这个网格中,存在一个由6个格子组成的最大区域,这些格子的数字编号满足相邻格子之间差值的绝对值小于等于1的条件。
示例2
  • 输入:
    2 3
    1 3 5
    4 1 3
    
  • 输出:
    1
    
    解释:在这个网格中,任意两个相邻格子之间的差值绝对值都大于1,因此机器人无法在不同格子之间移动,只能在单个格子内活动。

注意事项

  • 在编写代码时,要注意边界条件的处理,确保不会越界访问网格。
  • 使用标记数组来避免重复访问已经访问过的格子。
  • 在搜索过程中,要及时更新当前区域的大小,并在遍历完整个网格后找到并输出最大的区域大小。

当然,下面我将给出解决“机器人活动区域”问题的详细解题步骤,这个问题通常涉及到图的遍历算法,如深度优先搜索(DFS)或广度优先搜索(BFS)。为了简化,我们将使用DFS作为遍历方法。

解题步骤

1. 初始化
  • 输入处理:读取网格的行数M和列数N,以及网格中每个格子的数字编号。
  • 创建网格:根据输入数据,创建一个二维数组grid来存储网格,其中grid[i][j]表示第i行第j列的格子编号。
  • 创建访问标记数组:创建一个同样大小的二维布尔数组visited,用于标记网格中的格子是否已被访问过。初始时,所有格子都未被访问(即visited[i][j] = false)。
2. 深度优先搜索(DFS)
  • 定义DFS函数:该函数接受当前格子的行索引row、列索引col以及当前区域的大小size作为参数。
  • 边界检查:在尝试访问相邻格子之前,检查当前格子的行索引和列索引是否在网格范围内内(即0 <= row < M0 <= col < N)。
  • 访问标记:将当前格子标记为已访问(即visited[row][col] = true)。
  • 递归搜索:对于当前格子的每个相邻格子(上、下、左、右),如果它未被访问过(即!visited[newRow][newCol])且满足差值条件(即|grid[newRow][newCol] - grid[row][col]| <= 1),则递归调用DFS函数,并将相邻格子的行索引、列索引以及当前区域大小加1作为参数传递。
  • 更新区域大小:在DFS过程中,通过递归调用时的参数传递,不断更新当前区域的大小。
3. 遍历网格并应用DFS
  • 遍历网格中的每个格子。
  • 对于每个未访问过的格子(即!visited[i][j]),调用DFS函数,以该格子为起点开始搜索,并将初始区域大小设置为1。
  • 在每次DFS调用后,检查并更新找到的最大区域大小。
4. 输出结果
  • 遍历完整个网格后,输出找到的最大区域大小。

示例代码(Java)




public class RobotActivityArea {

    private static final int[][] DIRECTIONS = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; // 上下左右

    /**
     * 计算二维网格中最大的岛屿面积
     * 岛屿由1表示,水域由0表示,岛屿的定义是水平或垂直连接的1的集合
     * 此函数通过深度优先搜索(DFS)算法来遍历每个网格,找出最大的岛屿面积
     *
     * @param grid 二维网格,由0和1组成,0代表水域,1代表岛屿的一部分
     * @return 返回最大岛屿的面积如果网格为空或没有岛屿,则返回0
     */
    public static int maxArea(int[][] grid) {
        // 检查网格是否为空或者没有岛屿,如果是,则直接返回0
        if (grid == null || grid.length == 0 || grid[0].length == 0) {
            return 0;
        }

        // 初始化网格的行数和列数
        int rows = grid.length;
        int cols = grid[0].length;
        // 创建一个二维布尔数组,用于记录每个网格是否已经被访问过
        boolean[][] visited = new boolean[rows][cols];
        // 初始化最大岛屿面积为0
        int maxArea = 0;

        // 遍历每个网格
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                // 如果当前网格没有被访问过,则计算从这个网格出发的岛屿面积
                if (!visited[i][j]) {
                    int currentArea = dfs(grid, visited, i, j);
                    // 更新最大岛屿面积
                    maxArea = Math.max(maxArea, currentArea);
                }
            }
        }

        // 返回最大岛屿面积
        return maxArea;
    }

    /**
 * 深度优先搜索计算网格区域
 *
 * @param grid 二维网格数组,表示地图
 * @param visited 二维布尔数组,表示是否访问过
 * @param row 当前行位置
 * @param col 当前列位置
 * @return 返回从给定位置开始的网格区域大小
 */
private static int dfs(int[][] grid, boolean[][] visited, int row, int col) {
    // 检查grid和visited是否为空或null
    if (grid == null || grid.length == 0 || visited == null || visited.length == 0) {
        return 0;
    }

    // 获取网格的行数和列数
    int rows = grid.length;
    int cols = grid[0].length;

    // 检查当前位置是否越界或已被访问,如果是,则返回0
    if (row < 0 || row >= rows || col < 0 || col >= cols || visited[row][col]) {
        return 0;
    }

    // 将当前位置标记为已访问
    visited[row][col] = true;
    // 初始化区域计数为1,代表当前位置
    int area = 1;

    // 遍历四个方向(假设DIRECTIONS已定义为包含四个方向的数组:{-1, 0}, {1, 0}, {0, -1}, {0, 1})
    for (int[] direction : DIRECTIONS) {
        // 计算下一个位置的行和列
        int newRow = row + direction[0];
        int newCol = col + direction[1];
        // 如果下一个位置有效,则累加其区域
        if (isValid(grid, visited, newRow, newCol, grid[row][col])) {
            area += dfs(grid, visited, newRow, newCol);
        }
    }

    // 返回当前位置开始的区域大小
    return area;
}


    // 假设isValid方法已定义,用于检查给定位置是否为有效位置
    // 返回true如果位置有效,否则返回false
    private static boolean isValid(int[][] grid, boolean[][] visited, int row, int col, int prevValue) {
        // 检查位置是否越界和已被访问
        // 检查当前位置的值是否与前一个位置的值相同(这里假设我们只关心连续相同的值)
        // 根据实际情况可能需要更复杂的逻辑来判断有效性
        return row >= 0 && row < grid.length && col >= 0 && col < grid[0].length && !visited[row][col] && grid[row][col] == prevValue;
    }


    public static void main(String[] args) {
        int[][] grid = {
                {1, 2, 5, 2},
                {2, 4, 4, 5},
                {3, 5, 7, 1}
        };

        System.out.println("Max area: " + maxArea(grid)); 
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值