亲子游戏

华为OD机试

题目描述

宝宝和妈妈参加亲子游戏,在一个二维矩阵(N*N)的格子地图上,宝宝和妈妈抽签决定各自的位置,地图上每个格子有不同的糖果数量,部分格子有障碍物。

游戏规则是妈妈必须在最短的时间(每个单位时间只能走一步)到达宝宝的位置,路上的所有糖果都可以拿走,不能走障碍物的格子,只能上下左右走。

请问妈妈在最短到达宝宝位置的时间内最多拿到多少糖果(优先考虑最短时间到达的情况下尽可能多拿糖果)。

输入描述

第一行输入为 N,N 表示二维矩阵的大小。 之后 N 行,每行有 N 个值,表格矩阵每个位置的值,其中:

  • -3: 妈妈

  • -2: 宝宝

  • -1: 障碍

  • : 糖果数(0 表示没有糖果,但是可以走)

输出描述

输出妈妈在最短到达宝宝位置的时间内最多拿到多少糖果,行未无多余空格。

备注

地图最大 50 * 50

示例1

输入:
4
3 2 1 -3
1 -1 1 1
1 1 -1 2
-2 1 2 3

输出:
9

说明:
此地图有两条最短路径可到达宝宝位置,绿色线和黄色线都是最短路径6步,但黄色拿到的糖果更多,9个。

示例2

输入:
4
3 2 1 -3
-1 -1 1 1
1 1 -1 2
-2 1 -1 3

输出:
-1

说明:
此地图妈妈无法到达宝宝的位置。

题解

这道题是一个经典的 BFS(广度优先搜索)问题。妈妈需要在最短时间内从起点到达终点,并且在这个过程中尽可能多地收集糖果。可以通过 BFS 来同时处理路径最短和糖果最多的问题。

解题思路

  1. 数据结构选择
    • 使用 Deque(双端队列)来进行 BFS 搜索。
    • 使用一个二维数组 vis 来标记访问过的节点。
  2. 初始化
    • 从起点位置开始,初始化 Deque,并把起点加入队列。
    • 记录妈妈和宝宝的起始位置。
  3. BFS 搜索
    • 每次从队列中取出当前节点,检查是否到达终点。
    • 如果到达终点,更新最大糖果数量并标记为已找到结果。
    • 否则,将当前格子的糖果数加到总糖果数中。
    • 向四个方向探索相邻节点,将有效的节点加入队列。
  4. 终止条件
    • 如果队列为空,说明所有可行路径已经探索完毕。
    • 如果找到了终点,记录结果并输出。

复杂度分析

  • 时间复杂度:O(N^2),其中 N 是矩阵的大小,因为每个格子最多访问一次。
  • 空间复杂度:O(N^2),用于存储队列和访问标记数组。

C++

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int n;
    cin >> n;
    vector<vector<int>> grid(n, vector<int>(n));

    int sr, sc, tr, tc;
    for (int r = 0; r < n; r++) {
        for (int c = 0; c < n; c++) {
            cin >> grid[r][c];
            if (grid[r][c] == -3) {   // 妈妈的位置
                sr = r;
                sc = c;
            } else if (grid[r][c] == -2) {   // 宝宝的位置
                tr = r;
                tc = c;
            }
        }
    }

    // <拿到的糖果,<横坐标, 纵坐标>>
    deque<pair<int, pair<int, int>>> dq;
    vector<vector<bool>>             vis(n, vector(n, false));
    dq.push_back({0, {sr, sc}});

    bool hasResult = false;   // 是否已经到达宝宝的位置
    int  maxAns    = -1;   // 妈妈在最短到达宝宝位置的时间内最多拿到多少糖果
    int  dirs[]    = {-1, 0, 1, 0, -1};
    while (!dq.empty() && !hasResult) {
        size_t size = dq.size();
        for (size_t i = 0; i < size; i++) {
            auto pii = dq.front();
            dq.pop_front();
            int tot = pii.first, r = pii.second.first, c = pii.second.second;
            vis[r][c] = true;

            // 到达终点
            if (r == tr && c == tc) {
                hasResult = true;
                maxAns    = max(maxAns, tot);
            }

            // 拿到当前位置的糖果
            if (grid[r][c] > 0) tot += grid[r][c];

            // 向四周探索
            for (int j = 1; j < 5; j++) {
                int nr = r + dirs[j - 1], nc = c + dirs[j];
                if (nr < 0 || nc < 0 || nr >= n || nc >= n || vis[nr][nc] || grid[nr][nc] == -1)
                    continue;

                dq.push_back({tot, {nr, nc}});
            }
        }
    }

    cout << maxAns << endl;

    return 0;
}    

希望这个专栏能让您熟练掌握算法, 🎁🎁🎁 立即订阅

整理题解不易, 如果有帮助到您,请给点个赞 ‍❤️‍ 和收藏 ⭐,让更多的人看到。🙏🙏🙏

#面经##春招##秋招##华为od##笔试#
C++笔试真题题解 文章被收录于专栏

笔试真题题解

全部评论

相关推荐

12-05 18:09
已编辑
广东药科大学 后端工程师
点赞 评论 收藏
分享
11-13 14:37
门头沟学院 Java
点赞 评论 收藏
分享
评论
4
5
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务