【华为OD-E卷 - 欢乐的周末 100分(python、java、c++、js、c)】

【华为OD-E卷 - 欢乐的周末 100分(python、java、c++、js、c)】

题目

小华和小为是很要好的朋友,他们约定周末一起吃饭。
通过手机交流,他们在地图上选择了多个聚餐地点(由于自然地形等原因,部分聚餐地点不可达),求小华和小为都能到达的聚餐地点有多少个?

输入描述

  • 第一行输入m和n,m代表地图的长度,n代表地图的宽度。

第二行开始具体输入地图信息,地图信息包含:

0 为通畅的道路

1 为障碍物(且仅1为障碍物)

2 为小华或者小为,地图中必定有且仅有2个 (非障碍物)

3 为被选中的聚餐地点(非障碍物)

输出描述

  • 可以被两方都到达的聚餐地点数量,行末无空格

用例

用例一:
输入:
4 4
2 1 0 3
0 1 2 1
0 3 0 0
0 0 0 0
输出:
2
用例二:
输入:
4 4
2 1 2 3
0 1 0 0
0 1 0 0
0 1 0 0
输出:
0

python解法

  • 解题思路:
  • 输入处理:

读取输入的 m(行数)和 n(列数)。
读取 m 行的网格数据,并存入 grid 矩阵。
定义规则:

0:可以通行的空地。
1:墙壁,不能通行。
2:起点(有两个)。
3:关键地点(需要统计的地点)。
广度优先搜索(BFS):

从起点开始,使用 BFS 搜索所有可达的位置。
过程中记录访问过的节点,防止重复访问。
当遇到 3 时,加入 accessible 集合。
寻找起点:

遍历网格,找到所有 2 位置的坐标,存入 starts 列表。
求交集:

计算从华的起点和卫的起点分别能到达的 3 的位置。
取两个集合的交集,得到两个都能到达的关键地点。
输出:

输出交集的大小,即两个都能到达的 3 位置的数量

from collections import deque

# 读取输入的行数 m 和列数 n
m, n = map(int, input().split())

# 读取 m 行的网格数据,存入 grid 矩阵
grid = [list(map(int, input().split())) for _ in range(m)]

def bfs(start):
    """
    使用广度优先搜索(BFS)找到从起点可以到达的所有关键地点(值为3的格子)。
    
    :param start: (x, y) 起点坐标
    :return: 可达的关键地点集合(包含所有能到的值为3的坐标)
    """
    queue = deque([start])  # BFS 队列,初始包含起点
    visited = set([start])  # 记录访问过的点,防止重复搜索
    offsets = [(-1, 0), (1, 0), (0, -1), (0, 1)]  # 方向向量:上、下、左、右
    accessible = set()  # 记录可达的关键地点(值为3的位置)

    while queue:
        x, y = queue.popleft()  # 取出队列的当前搜索点

        # 如果当前位置是关键地点(值为3),加入集合
        if grid[x][y] == 3:
            accessible.add((x, y))

        # 遍历四个方向
        for dx, dy in offsets:
            nx, ny = x + dx, y + dy  # 计算新坐标
            # 判断新坐标是否在范围内,且不为墙(值为1),并且未访问过
            if 0 <= nx < m and 0 <= ny < n and grid[nx][ny] != 1 and (nx, ny) not in visited:
                visited.add((nx, ny))  # 标记为已访问
                queue.append((nx, ny))  # 加入队列继续搜索

    return accessible  # 返回可达的关键地点集合

# 查找所有起点(值为2的坐标)
starts = [(i, j) for i in range(m) for j in range(n) if grid[i][j] == 2]

# 分别计算从两个起点出发能够到达的关键地点
reachable_hua = bfs(starts[0])  # 第一个起点
reachable_wei = bfs(starts[1])  # 第二个起点

# 计算两个集合的交集,即两人都能到达的关键地点
common_places = reachable_hua & reachable_wei

# 输出能够被两人都到达的关键地点的数量
print(len(common_places))

java解法

  • 解题思路
  • 输入处理:读取输入的网格矩阵,包括行数 m 和列数 n,以及每个单元格的值。

定义规则:

0 表示可以通行的空地。
1 表示墙壁,无法通过。
2 表示起点。
3 表示需要统计的关键地点。
找到起点:分别找到两个起点(假设输入中有两个标记为 2 的点)。

深度优先搜索(DFS):从每个起点开始,使用 DFS 标记所有能够到达的点,分别记录华和卫能到达的位置。

统计结果:遍历整个网格,对于每个标记为 3 的位置,如果华和卫都能到达,则计数加一。

输出:输出能够被两个人都到达的关键地点的数量

import java.util.*;

public class Main {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        // 输入矩阵的行数 m 和列数 n
        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(countCommonPlaces(grid));
    }

    public static int countCommonPlaces(int[][] grid) {
        int m = grid.length;
        int n = grid[0].length;

        // 记录华和卫是否到达过的地点
        boolean[][] visitedByHua = new boolean[m][n];
        boolean[][] visitedByWei = new boolean[m][n];

        // 找到华的起点 (2 表示起点)
        int[] huaStart = findStart(grid, 2);
        dfs(grid, visitedByHua, huaStart[0], huaStart[1], m, n);

        // 重新找卫的起点 (因为华的起点已经被清除了)
        int[] weiStart = findStart(grid, 2);
        dfs(grid, visitedByWei, weiStart[0], weiStart[1], m, n);

        int count = 0;
        // 统计华和卫均能到达的地点 (3 表示地点)
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (grid[i][j] == 3 && visitedByHua[i][j] && visitedByWei[i][j]) {
                    count++;
                }
            }
        }

        return count;
    }

    // 找到第一个指定值的坐标
    public static int[] findStart(int[][] grid, int target) {
        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[0].length; j++) {
                if (grid[i][j] == target) {
                    grid[i][j] = 0;  // 避免重复找到同一个起点
                    return new int[]{i, j};
                }
            }
        }
        return null;
    }

    // 深度优先搜索函数,标记所有能达的地点
    public static void dfs(int[][] grid, boolean[][] visited, int row, int col, int m, int n) {
        if (row < 0 || row >= m || col < 0 || col >= n || grid[row][col] == 1 || visited[row][col]) {
            return; // 超出边界或遇到墙或已访问过的地点
        }

        visited[row][col] = true;

        // 向上、向下、向左、向右递归调用
        dfs(grid, visited, row - 1, col, m, n);
        dfs(grid, visited, row + 1, col, m, n);
        dfs(grid, visited, row, col - 1, m, n);
        dfs(grid, visited, row, col + 1, m, n);
    }
}

C++解法

  • 解题思路
更新中

C解法

  • 解题思路

更新中

JS解法

  • 解题思路

更新中

注意:

如果发现代码有用例覆盖不到的情况,欢迎反馈!会在第一时间修正,更新。
解题不易,如对您有帮助,欢迎点赞/收藏

你可能感兴趣的:(算法题,华为od,(A+B+C+D+E,卷)收录分享,华为od,python,java,c++,javascript)