华为OD机试真题中的“学生方阵”题目是一道有趣的编程挑战。以下是对该题目的详细解析:
一、题目描述
学校组织活动,将学生排成一个矩形方阵。题目要求在矩形方阵中找到最大的位置相连的男生数量,这个相连位置在一个直线上,方向可以是水平的、垂直的、成对角线的或者呈反对角线的。
注:学生个数不会超过10000
二、输入描述
- 输入的第一行为矩阵的行数和列数,接下来的n行为矩阵元素,元素间用”,”分隔。
- 接下来的n行为矩阵元素,元素间用逗号分隔。矩阵中的元素表示学生的性别,“M”代表男生,“F”代表女生。
三、输出描述
输出一个整数,表示矩阵中最长的位置相连的男生个数。
示例
输入
3,4
F,M,M,F
F,M,M,F
F,F,F,M
输出
3
输入
1,2
M,M
输出
2
输入
2,1
M
F
输出
1
四、解题思路
- 遍历矩阵:首先,需要遍历矩阵中的每一个元素,以每一个“M”(男生)作为起点,开始寻找相连的男生数量。
- 定义方向:为了找到所有可能相连的男生,需要定义四个方向(水平、垂直、正对角线、反对角线)进行搜索。这可以通过一个二维方向数组来实现。
- 深度优先遍历:从每一个男生起点开始,沿着上述四个方向进行深度优先遍历,记录每个方向上相连的男生数量,并保留最大值。
- 更新结果:在遍历过程中,不断更新找到的最大相连男生数量。
五、示例代码
import java.util.Scanner;
public class StudentSquare {
static int[][] directions = {{0, 1}, {1, 1}, {1, 0}, {1, -1}}; // 方向数组,分别表示右、右下、下、左下
/**
* 主函数,用于寻找矩阵中从男生(M)出发的最大路径长度
*/
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 读取并解析输入的矩阵行列数
String[] input = scanner.nextLine().split(",");
int m = Integer.parseInt(input[0]); // 矩阵行数
int n = Integer.parseInt(input[1]); // 矩阵列数
String[][] matrix = new String[m][n];
// 读取矩阵
for (int i = 0; i < m; i++) {
String[] line = scanner.nextLine().split(",");
for (int j = 0; j < n; j++) {
matrix[i][j] = line[j];
}
}
// 初始化最大路径长度为0
int maxLen = 0;
// 遍历矩阵中的每一个男生
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (matrix[i][j].equals("M")) {
int len = 0;
// 对每一个方向进行深度优先遍历
for (int[] dir : directions) {
len = Math.max(len, getMaxLength(matrix, i, j, dir[0], dir[1]));
}
maxLen = Math.max(maxLen, len);
}
}
}
// 输出最大路径长度
System.out.println(maxLen);
}
// 使用深度优先遍历算法获取相连男生的最大数量
// 该方法递归地检查在一个矩阵中,从某个起点开始,沿着指定方向,连续的男生("M")的最大数量
private static int getMaxLength(String[][] matrix, int x, int y, int dx, int dy) {
// 获取矩阵的行数和列数
int m = matrix.length;
int n = matrix[0].length;
// 检查当前位置是否超出矩阵边界,或者当前位置不是男生("M")
if (x < 0 || x >= m || y < 0 || y >= n || !matrix[x][y].equals("M")) {
// 如果条件满足,说明当前位置无效或不是男生,返回0,表示没有相连的男生
return 0;
}
// 如果当前位置是男生("M"),则递归地向指定方向移动一步,并累加计数
// 通过递归调用自身,不断沿dx和dy方向前进,直到不满足条件时,返回累加的数量
return 1 + getMaxLength(matrix, x + dx, y + dy, dx, dy);
}
}
六、运行示例解析
输入:
3,4
F,M,M,F
F,M,M,F
F,F,F,M
步骤解析:
-
初始化:
- 读取输入的行数
m = 3和列数n = 4。 - 创建一个
3x4的字符串矩阵matrix。
- 读取输入的行数
-
读取矩阵:
- 根据输入,填充矩阵
matrix如下:[ ["F", "M", "M", "F"], ["F", "M", "M", "F"], ["F", "F", "F", "M"] ]
- 根据输入,填充矩阵
-
遍历矩阵:
- 从矩阵的每一个位置
(i, j)开始,如果位置上是男生"M",则进行深度优先遍历。
- 从矩阵的每一个位置
-
深度优先遍历:
- 从每个男生位置
(i, j)开始,沿着四个方向(右、右下、下、左下)进行遍历。 - 使用递归函数
getMaxLength计算从当前位置开始,沿着指定方向可以连续遇到的男生数量。
- 从每个男生位置
-
计算最大路径长度:
- 对于每个男生位置
(i, j),计算其在四个方向上的最大路径长度,并更新全局最大路径长度maxLen。
- 对于每个男生位置
详细解析:
-
对于位置
(0, 1)(即第一行第二列的男生"M"):- 向右(方向
{0, 1}):连续两个"M",长度为 2。 - 向右下(方向
{1, 1}):第一个方向是(1, 2)是"M",但第二个方向(2, 3)是"F",长度为 1。 - 向下(方向
{1, 0}):超出边界。 - 向左下(方向
{1, -1}):第一个方向是(1, 0)是"F",长度为 0。 - 对于
(0, 1)的最大路径长度为 2。
- 向右(方向
-
对于位置
(1, 1)(即第二行第二列的男生"M"):- 向右(方向
{0, 1}):连续两个"M",长度为 2。 - 向右下(方向
{1, 1}):第一个方向是(2, 2)是"M",但第二个方向(3, 3)超出边界,长度为 2。 - 向下(方向
{1, 0}):超出边界。 - 向左下(方向
{1, -1}):第一个方向是(2, 0)是"F",长度为 0。 - 对于
(1, 1)的最大路径长度为 2。
- 向右(方向
-
对于其他男生位置,进行类似的计算。
-
最终,全局最大路径长度
maxLen是 3,因为从(1, 1)向右下方向(2, 2)和(1, 2)可以连续遇到三个男生"M"。
输出:
3
注意:在给出的代码中,方向数组和递归逻辑是正确的,但需要注意的是,题目中要求的是“最大的位置相连的男生数量”,而不仅仅是某个方向上的连续男生数量。因此,理论上应该对每个男生位置 (i, j) 进行四个方向的搜索,并考虑所有可能的路径(包括回头和变向),但这样做复杂度会非常高。在实际情况下,为了简化问题,通常只考虑单向(不回头)的连续路径长度,如上述解析所示。如果要考虑所有可能的路径组合,则需要使用更复杂的算法(如动态规划或回溯算法),并可能需要对每个位置进行多次访问和标记。然而,对于本题目的简单解法,上述解析已经足够。
六、注意事项
- 边界条件:在遍历过程中,需要注意边界条件,避免数组越界。
- 效率优化:由于矩阵的大小可能达到10000x10000,因此需要考虑算法的效率。上述代码使用了深度优先遍历,但在实际应用中,可能需要考虑使用动态规划或其他优化算法来提高效率。
- 输入验证:在实际应用中,还需要对输入进行验证,确保输入的数据符合题目要求。
综上所述,华为OD机试真题中的“学生方阵”题目是一道考察矩阵遍历和深度优先遍历的编程题。通过理解题目要求、定义方向数组、进行深度优先遍历以及更新结果等步骤,可以求解出矩阵中最长的位置相连的男生数量。

3714

被折叠的 条评论
为什么被折叠?



