目录
题目描述
宝宝和妈妈参加亲子游戏,在一个二维矩阵(N×N)的格子地图上,宝宝和妈妈抽签决定各自的位置。地图上每个格子有不同的糖果数量,部分格子有障碍物。
游戏规则:
妈妈必须在最短时间(每单位时间走一步)到达宝宝的位置,只能上下左右移动,不能走障碍物。
移动过程中经过的格子糖果可以全部拿走。
优先保证最短时间到达,其次在最短路径中尽可能多拿糖果。
输入描述
第一行输入矩阵大小N(最大50×50)。
之后N行,每行N个整数,表示格子属性:
-3:妈妈
-2:宝宝
-1:障碍
≥0:糖果数(0表示无糖果但可通行)。
输出描述
输出妈妈在最短时间内到达宝宝位置时能拿到的最大糖果数;若无法到达,输出-1。
示例
输入:
4
3 2 1 -3
1 -1 1 1
1 1 -1 2
-2 1 2 3
输出:
9
解释:两条最短路径(6步),其中一条路径糖果总和为9。
为什么刷华为OD机试题?
华为OD(Outsourcing Dispacth)是华为与外企德科联合招聘的精英外包模式,员工由德科签订合同并派驻华为工作。
OD员工工作内容、管理方式与华为正式员工高度对齐,同工同酬,如:工作内容、福利(如五险一金、加班费、夜宵补贴等)基本一致;
且有机会通过绩效考核转为正式员工(需入职满1年、两次绩效A并通过可信认证考试)。
与传统外包的区别:
薪资对标:D1-D5等级对应华为13-17级,月薪范围9k-29k,年终奖2-4个月(绩效A可拿满)。
发展路径:参与核心项目开发,与华为员工共用技术晋升通道,转正后享股票分红(需职级≥15级)。
华为OD机试是华为对外包岗位选拔人才的核心环节,为在线编程考试,主要考察算法设计、数据结构、代码调试能力。是入职流程中的核心环节,直接影响后续面试资格和薪资定级;
据统计,机试通过率约75%,非目标院校需300+分(目标院校150+分),未通过需等待半年冷冻期。
题目构成:
3道编程题:2道100分题(逻辑分析/字符串处理)+1道200分题(动态规划/图论等),总分400分,难度分布为简单+简单+中等/困难。
考试时间:150分钟,支持本地IDE编码后复制提交,但需注意代码重复率(>80%可能判作弊)。
题库特点:
根据历史记录,华为OD面试的考卷每季度(Q1-Q4)更换一次算法考试题目:旧题(占比66%)+新题(占比33%),抽中原题概率约80%。
查重机制:代码相似度超80%判作弊,建议修改变量名、调整逻辑顺序。
评分标准:按测试用例通过比例得分,非目标院校需≥300分,目标院校≥150分即可;
思路
核心逻辑是使用 BFS(广度优先搜索)在网格中寻找从起点到终点的最短路径,并在所有最短路径中收集最多的糖果,最终输出最大糖果数(若无法到达终点则输出 - 1)。以下是详细逻辑拆解:
1. 输入处理与初始化
- 读取网格规模:首先读取整数
n,表示网格是n×n的二维数组。 - 读取网格数据:通过双重循环读取
n×n的网格数据到vec中,同时记录:- 起点坐标
(startx, starty):网格中值为-3的位置(代表起点)。 - 终点坐标
(endx, endy):网格中值为-2的位置(代表终点)。
- 起点坐标
- 方向数组:
disX和disY分别存储 x 轴和 y 轴的偏移量,对应 “上、右、下、左” 四个方向(用于遍历相邻单元格)。
2. 核心数据结构
- 队列
q:BFS 的核心容器,用于按顺序存储待处理的网格坐标(保证 “先处理近距离位置”)。 - 距离数组
dist:dist[i][j]记录从起点到(i,j)的最短步数,初始值为INT_MAX(表示 “尚未到达”)。 - 糖果数组
maxcandy:maxcandy[i][j]记录在 “最短步数” 前提下,到达(i,j)时能收集的最大糖果数,初始值为-1(表示 “未收集到糖果”)。
3. BFS 搜索过程(核心逻辑)
BFS 的本质是 “按距离分层扩散”,确保首次到达某位置时的步数为最短路径。这里额外处理了 “相同步数下最大化糖果数” 的需求。
初始化起点:
- 起点的最短距离
dist[startx][starty]设为0(距离自己 0 步)。 - 起点的初始糖果数
maxcandy[startx][starty]设为0(尚未收集任何糖果)。 - 将起点坐标
(startx, starty)加入队列,开始 BFS。
循环处理队列中的位置:
- 取出队首位置:获取当前处理的坐标
(x,y),并弹出队列。 - 获取当前状态:记录当前位置的最短距离
curDist和最大糖果数curCandy。 - 遍历四个方向的邻居:通过方向数组计算邻居坐标
(dx, dy)(dx = x + disX[i],dy = y + disY[i])。 - 有效性检查:
- 边界检查:
dx和dy必须在[0, n-1]范围内(不超出网格)。 - 障碍物检查:若
vec[dx][dy] == -1(障碍物),则跳过该邻居。
- 边界检查:
- 计算新状态:
- 新距离
newDist:当前距离 + 1(移动一步到邻居)。 - 新糖果数
newCandy:当前糖果数 + 邻居位置的糖果(若邻居有糖果,即vec[dx][dy] > 0)。
- 新距离
- 更新状态并入队:
- 若
newDist < dist[dx][dy]:找到更短的路径,更新dist[dx][dy]为newDist,maxcandy[dx][dy]为newCandy,并将(dx, dy)入队(继续扩散)。 - 若
newDist == dist[dx][dy]且newCandy > maxcandy[dx][dy]:路径长度相同,但能收集更多糖果,更新maxcandy[dx][dy]为newCandy,并将(dx, dy)入队(其邻居可能因糖果数更新而受益)。
- 若
4. 输出结果
- 若
dist[endx][endy] != INT_MAX:说明终点可达,输出终点的最大糖果数maxcandy[endx][endy]。 - 否则:终点不可达,输出
-1。
代码
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
int main() {
int n; cin >> n;
vector<vector<int>> vec(n, vector<int>(n));
int startx, starty,endx,endy;
for (int i = 0; i < n;i++) {
for (int j = 0; j < n; j++) {
cin >> vec[i][j];
if (vec[i][j] == -3) {
startx = i;
starty = j;
}
if (vec[i][j] == -2) {
endx = i;
endy = j;
}
}
}
//上右下左
int disX[4] = { -1,0,1,0 };
int disY[4] = { 0,1,0,-1 };
queue<pair<int, int>> q;
q.push({startx, starty});
vector<vector<int>> dist(n, vector<int>(n,INT_MAX));
vector<vector<int>> maxcandy(n, vector<int>(n, -1));
dist[startx][starty] = 0;
maxcandy[startx][starty] = 0;
while (!q.empty()) {
int x= q.front().first;
int y = q.front().second;
q.pop();
int curCandy = maxcandy[x][y];
int curDist = dist[x][y];
for (int i = 0; i < 4; i++) {
int dx = x + disX[i];
int dy = y + disY[i];
if (dx < 0 || dy < 0 || dx >= n || dy >= n)continue;
if (vec[dx][dy] == -1)continue;
int newDist = curDist + 1;
int newCandy = curCandy;
if (vec[dx][dy] > 0) {
newCandy += vec[dx][dy];
}
if (newDist < dist[dx][dy]) {
dist[dx][dy] = newDist;
maxcandy[dx][dy] = newCandy;
q.push({ dx,dy });
}else if (newDist == dist[dx][dy]&&newCandy> curCandy) {
maxcandy[dx][dy] = newCandy;
q.push({ dx,dy });
}
}
}
if (dist[endx][endy] != INT_MAX)cout << maxcandy[endx][endy];
else cout << -1;
return 0;
}
对您有帮助的话,可以点个免费的赞吗~

&spm=1001.2101.3001.5002&articleId=151873064&d=1&t=3&u=4c188ecbdeb447a8a1068d3a24b2cef2)
2万+

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



