网易雷火笔试 网易雷火笔试题 网易笔试 0831
笔试时间:2025年8月31日
往年笔试合集:
第一题:炼金术士
小师妹是一位热爱炼金术的学徒,最近接到了一批紧急订单。她需要利用仓库中的炼金资材,合理规划生产,尽可能满足客户的需求。仓库中存有一批炼金资材,每份资材有对应的等级(1-10级)。小师妹可以:使用一份资材直接制作出一瓶相同等级的炼金药剂。将两瓶相同等级的药剂合成一瓶高一级的药剂(例如:2瓶1级药剂可以合成1瓶2级药剂)。现在有一批订单,每个订单要求提供特定等级的一瓶药剂。小师妹希望能够完成所有订单,或在资材不足的情况下完成尽可能多的订单。
输入描述
第一行:两个整数n和m,分别表示仓库中的炼金资材数量和炼金订单数量。
第二行:n个整数,每个整数范围在1到10之间,表示仓库里的炼金资材等级。
第三行:m个整数,每个整数范围在1到10之间,表示每个订单所需药剂的等级。
补充说明:每个订单,只能用对应等级的药剂来提交。
样例输入
8 5
1 3 4 9 6 6 4 8
1 5 9 3 7
样例输出
7
参考题解
问题的核心在于判断是两种完全不同的策略,这取决于我们是否能满足所有订单。因此,解题思路分为两步:可行性判断: 首先,我们需要判断仓库中的材料是否足够满足所有订单。这里采用一种贪心策略:从最低等级(1级)开始向上检查。对于每个等级,我们计算可用的药剂(包括原始材料和由下一级合成的药剂)。如果当前等级的可用药剂数量少于订单需求,那么就无法满足所有订单。反之,如果能满足,多余的药剂可以两两合成为更高级的药剂,计入到下一级的可用药剂中。如果这个过程能顺利进行到最高级,说明所有订单都可以被满足。根据可行性选择策略:如果可以满足所有订单:目标是使用最少的原材料。为了最节省,我们应该优先使用高级材料满足高级订单,因为用低级材料合成高级药剂成本很高。所以,我们从最高等级(10级)开始向下倒推计算。对于每个等级,我们先用该等级的库存材料满足需求(包括该等级的订单和更高级别传递下来的合成需求)。如果库存不足,缺口就必须由下一级材料合成来补充,这个新的需求会乘以2后传递给下一级。最终,将所有等级实际消耗的原材料数量相加即可。如果无法满足所有订单:目标是完成尽可能多的订单。为了完成更多订单,我们应该优先满足成本低的订单,也就是低等级的订单。所以,我们从最低等级(1级)开始向上正向计算。在每个等级,用所有可用的药剂(原材料+低级合成)去满足该等级的订单,能满足多少就满足多少。然后,将剩余的药剂合成到更高级别。将每个级别能满足的订单数累加,就是最终结果。
C++:
#include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); long long n, m; if (!(cin >> n >> m)) return 0; // 下标 0..11,实际使用 1..10,11 是余量“溢出位” array<long long, 12> materials_count{}; array<long long, 12> orders_count{}; for (long long i = 0; i < n; ++i) { int x; cin >> x; if (0 <= x && x < 12) materials_count[x]++; } for (long long i = 0; i < m; ++i) { int x; cin >> x; if (0 <= x && x < 12) orders_count[x]++; } auto potions_check = materials_count; bool can_fulfill_all = true; for (int i = 1; i <= 10; ++i) { if (potions_check[i] < orders_count[i]) { can_fulfill_all = false; break; } potions_check[i + 1] += (potions_check[i] - orders_count[i]) / 2; } if (can_fulfill_all) { array<long long, 12> needed_from_synthesis{}; long long total_used_materials = 0; for (int i = 10; i >= 1; --i) { long long total_demand = orders_count[i] + needed_from_synthesis[i]; long long used_at_this_level = min(total_demand, materials_count[i]); total_used_materials += used_at_this_level; long long deficit = total_demand - used_at_this_level; if (i > 1) needed_from_synthesis[i - 1] = deficit * 2; } cout << total_used_materials << "\n"; } else { auto potions_greedy = materials_count; long long fulfilled_count = 0; for (int i = 1; i <= 10; ++i) { long long can_fulfill_at_level = min(potions_greedy[i], orders_count[i]); fulfilled_count += can_fulfill_at_level; potions_greedy[i + 1] += (potions_greedy[i] - can_fulfill_at_level) / 2; } cout << fulfilled_count << "\n"; } return 0; }
Java:
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.Arrays; import java.util.StringTokenizer; publicclass Main { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer st = new StringTokenizer(br.readLine()); int n = Integer.parseInt(st.nextToken()); int m = Integer.parseInt(st.nextToken()); long[] materials_count = newlong[12]; st = new StringTokenizer(br.readLine()); for (int i = 0; i < n; i++) { materials_count[Integer.parseInt(st.nextToken())]++; } long[] orders_count = newlong[12]; st = new StringTokenizer(br.readLine()); for (int i = 0; i < m; i++) { orders_count[Integer.parseInt(st.nextToken())]++; } long[] potions_check = Arrays.copyOf(materials_count, 12); boolean can_fulfill_all = true; for (int i = 1; i <= 10; i++) { if (potions_check[i] < orders_count[i]) { can_fulfill_all = false; break; } potions_check[i + 1] += (potions_check[i] - orders_count[i]) / 2; } if (can_fulfill_all) { long[] needed_from_synthesis = newlong[12]; long total_used_materials = 0; for (int i = 10; i >= 1; i--) { long total_demand = orders_count[i] + needed_from_synthesis[i]; long used_at_this_level = Math.min(total_demand, materials_count[i]); total_used_materials += used_at_this_level; long deficit = total_demand - used_at_this_level; if (i > 1) { needed_from_synthesis[i - 1] = deficit * 2; } } System.out.println(total_used_materials); } else { long[] potions_greedy = Arrays.copyOf(materials_count, 12); long fulfilled_count = 0; for (int i = 1; i <= 10; i++) { long can_fulfill_at_level = Math.min(potions_greedy[i], orders_count[i]); fulfilled_count += can_fulfill_at_level; potions_greedy[i + 1] += (potions_greedy[i] - can_fulfill_at_level) / 2; } System.out.println(fulfilled_count); } } }
Python:
import sys def main(): data = sys.stdin.read().strip().split() it = iter(data) n = int(next(it)); m = int(next(it)) materials_count = [0] * 12 # 使用下标 1..10,11 为溢出位 for _ in range(n): x = int(next(it)) if 0 <= x < 12: materials_count[x] += 1 orders_count = [0] * 12 for _ in range(m): x = int(next(it)) if 0 <= x < 12: orders_count[x] += 1 potions_check = materials_count[:] # 前向检验是否能全部满足 can_fulfill_all = True for i in range(1, 11): if potions_check[i] < orders_count[i]: can_fulfill_all = False break potions_check[i + 1] += (potions_check[i] - orders_count[i]) // 2 if can_fulfill_all: needed_from_synthesis = [0] * 12 total_used_materials = 0 for i in range(10, 0, -1): total_demand = orders_count[i] + needed_from_synthesis[i] used_at_this_level = min(total_demand, materials_count[i]) total_used_materials += used_at_this_level deficit = total_demand - used_at_this_level if i > 1: needed_from_synthesis[i - 1] = deficit * 2 print(total_used_materials) else: potions_greedy = materials_count[:] fulfilled_count = 0 for i in range(1, 11): can_fulfill_at_level = min(potions_greedy[i], orders_count[i]) fulfilled_count += can_fulfill_at_level potions_greedy[i + 1] += (potions_greedy[i] - can_fulfill_at_level) // 2 print(fulfilled_count) if __name__ == "__main__": main()
第二题:采集能量
在《无主星消》的太空战场中,玩家需操控飞船从起点(S)出发,在n*m的网格中以最短时间采集一定能量。飞船每次仅能向上下左右四个方向移动一个网格,能量必须以固定顺序被采集,飞船触碰到能量即视为采集能量。一共有5个能量,依次编号为1~5,玩家必须先采集编号小的能量,即先采集1号,再采集2号......最终采集5号能量。需要你帮玩家算一下,玩家最少移动几次可以采集完5个能量。
网格包含以下元素:
#: 不可穿越的障碍物
.: 可自由航行的太空区域
1~5: 表示5个能量的编号
S: 飞船起点
输入描述
首行:n m
后续n行,每行m个字符表示n*m的网格的信息。
输出描述
玩家最少所需的移动次数,数据保证一定有解。
样例输入
4 4
1.2.
.##3
.##4
S..5
样例输出
9
参考题解
问题分解:由于能量点必须按 1 到 5 的固定顺序采集,整个复杂的路径规划问题可以被分解为 5 个独立的、连续的最短路径问题:从起点 S 到 1 号能量点。从 1 号到 2 号能量点。从 2 号到 3 号能量点。从 3 号到 4 号能量点。从 4 号到 5 号能量点。核心算法:对于每一个子问题,这都是一个典型的在网格中寻找两点间最短路径的问题。广度优先搜索(BFS)是解决此类问题的标准且最高效的算法。关键约束处理:在为某个阶段(例如,从 1 号点走到 2 号点)进行 BFS 搜索时,必须确保路径不会“提前”经过后续的能量点(例如 3、4、5)。因此,在每次运行 BFS 之前,需要将所有尚未轮到采集的能量点在地图上临时标记为不可通行的障碍物。结果汇总:依次对上述 5 个阶段执行 BFS 计算,并将每个阶段得到的最短移动次数累加起来,最终的总和就是玩家完成任务所需的最少总移动次数。
C++:
#include <bits/stdc++.h> using namespace std; int n, m; vector<string> grid; int dirs[4][2] = {{0,1},{0,-1},{1,0},{-1,0}}; struct Node { int x, y; }; int bfs(Node start, Node end, int targetId, const array<optional<Node>, 6>& points) { vector<vector<int>> dist(n, vector<int>(m, -1)); vector<vector<char>> forbid(n, vector<char>(m, 0)); for (int id = targetId + 1; id <= 5; ++id) { if (points[id].has_value()) { auto p = points[id].value(); forbid[p.x][p.y] = 1; } } queue<Node> q; q.push(start); dist[start.x][start.y] = 0; while (!q.empty()) { Node cur = q.front(); q.pop(); if (cur.x == end.x && cur.y == end.y) return dist[cur.x][cur.y]; for (auto &d : dirs) { int nx = cur.x + d[0], ny = cur.y + d[1]; if (nx>=0 && nx<n && ny>=0 && ny<m && grid[nx][ny] != '#' && dist[nx][ny] == -1 && !forbid[nx][ny]) { dist[nx][ny] = dist[cur.x][cur.y] + 1; q.push({nx, ny}); } } } return -1; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); if (!(cin >> n >> m)) return 0; grid.assign(n, string()); array<optional<Node>, 6> points; // 0:S, 1..5 for (int i = 0; i < n; ++i) { cin >> grid[i]; for (int j = 0; j < m; ++j) { char c = grid[i][j]; if (c == 'S') points[0] = Node{i, j}; else if (isdigit(static_cast<unsigned char>(c))) { int id = c - '0'; if (1 <= id && id <= 5) points[id] = Node{i, j}; } } } long long total = 0; for (int i = 0; i < 5; ++i) { // 假设这些点都存在,和原 Java 一致 int d = bfs(points[i].value(), points[i+1].value(), i+1, points); total += d; // 若不可达则加 -1,与原逻辑一致 } cout << total << "\n"; return 0; }
Java:
import java.util.LinkedList; import java.util.Queue; import java.util.Scanner; publicclass Main { staticint n; staticint m; staticchar[][] grid; staticint[][] dirs = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; staticclass Node { int x, y; Node(int x, int y) { this.x = x; this.y = y; } } p
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
2025打怪升级记录,大厂笔试合集 C++, Java, Python等多种语言做法集合指南