网易笔试 网易春招实习 网易笔试真题解析 0402

笔试时间:2026年4月2日

往年笔试合集:

2023春招秋招笔试合集

2024春招秋招笔试合集

第一题:沙场点兵

题目

在网易旗舰级武侠游戏《逆水寒》的"宋辽边境"战场玩法中,宋辽两军正隔河对峙。

辽军统帅为了挫败我方士气,摆下了"连环阵":他们派出了 n 支精锐的先锋小队,并公开了这 n 支小队出战的先后顺序以及每一支小队的"战力值"。

作为宋军的战术指挥官,你手下同样拥有 n 支蓄势待发的铁骑小队,每支小队的"战力值"你也了如指掌。根据战场规则,两军将进行 n 轮一对一的"阵前对决":

每一轮,双方各派出一支小队进行厮杀;战力值较高的小队将全歼对手并获胜(积 1 分);若战力值相同,由于辽军占据地利,判定辽军获胜(宋军积 0 分,辽军积 1 分)。

战国时,齐威王与田忌赛马的故事广为人知,你也想成为如田忌一般的智将,带领你麾下的将士赢得胜利。请判断,是否存在一种排兵布阵的策略,使得我军最终的胜场数严格大于辽军的胜场数?

输入描述

每个测试文件均包含多组测试数据。第一行输入一个整数 T 表示演练的数据组数。每组测试数据描述如下:

  • 第一行一个整数 n(n 为奇数),表示双方派出的小队数量。
  • 第二行包含 n 个整数,表示我军(宋军)每支小队的战力值。
  • 第三行包含 n 个整数,表示敌军(辽军)的出战顺序及其战力值。

保证所有测试中 n 的总和不超过 2 × 10^5。

输出描述

输出 T 行。对每组数据,若通过合理排兵布阵能使得我军胜场数 > 败场数,输出 YES;否则输出 NO

样例输入

2
5
2 5 7 1 6
3 5 6 2 7
3
3 3 3
3 3 3

样例输出

YES
NO

样例说明

对于第一组测试数据,一种最佳出兵顺序如下:

  • 第一阵:派战力 2 迎战辽军 2(因相同,辽胜)
  • 第二阵:派战力 5 迎战辽军 3(宋胜)
  • 第三阵:派战力 6 迎战辽军 5(宋胜)
  • 第四阵:派战力 7 迎战辽军 6(宋胜)
  • 第五阵:派战力 1 迎战辽军 7(辽胜)

最终宋军 3 胜 2 负,大破辽军,输出 YES

参考题解

解题思路:

该问题本质上是"田忌赛马"贪心策略的变体。为了获得尽可能多的胜场,首先将双方的战力值数组进行升序排序。通过双指针贪心法,尝试用我方当前最弱的兵力去对抗敌方最弱的兵力:

  • 如果能赢,则匹配这对组合并增加胜场;
  • 如果不能赢(即我方最弱兵力小于或等于敌方最弱兵力),则该兵力无法战胜敌方任何剩余兵力,应将其消耗掉,转而使用我方后续更强的兵力尝试匹配。

由于题目给出 n 为奇数,且要求胜场数严格大于败场数,因此最终只需判断最大胜场数是否超过 n/2(即至少达到 (n+1)/2 场)即可判定为 YES

C++:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    int T;
    cin >> T;
    while (T--) {
        int n;
        cin >> n;
        vector<ll> song(n), liao(n);
        for (int i = 0; i < n; i++) cin >> song[i];
        for (int i = 0; i < n; i++) cin >> liao[i];
        sort(song.begin(), song.end());
        sort(liao.begin(), liao.end());
        int victories = 0;
        int enemyPtr = 0;
        for (int i = 0; i < n; i++) {
            if (song[i] > liao[enemyPtr]) {
                victories++;
                enemyPtr++;
            }
        }
        cout << (victories > n / 2 ? "YES" : "NO") << "\n";
    }
    return 0;
}

Java:

import java.util.*;
import java.io.*;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        String firstLine = reader.readLine();
        if (firstLine == null) return;
        int testCases = Integer.parseInt(firstLine.trim());
        PrintWriter out = new PrintWriter(System.out);
        while (testCases-- > 0) {
            int totalCount = Integer.parseInt(reader.readLine().trim());
            long[] songArmy = new long[totalCount];
            long[] liaoArmy = new long[totalCount];
            StringTokenizer st1 = new StringTokenizer(reader.readLine());
            for (int i = 0; i < totalCount; i++) {
                songArmy[i] = Long.parseLong(st1.nextToken());
            }
            StringTokenizer st2 = new StringTokenizer(reader.readLine());
            for (int i = 0; i < totalCount; i++) {
                liaoArmy[i] = Long.parseLong(st2.nextToken());
            }
            Arrays.sort(songArmy);
            Arrays.sort(liaoArmy);
            int victories = 0;
            int enemyPtr = 0;
            for (int ourPtr = 0; ourPtr < totalCount; ourPtr++) {
                if (songArmy[ourPtr] > liaoArmy[enemyPtr]) {
                    victories++;
                    enemyPtr++;
                }
            }
            if (victories > totalCount / 2) {
                out.println("YES");
            } else {
                out.println("NO");
            }
        }
        out.flush();
    }
}

Python:

import sys
input = sys.stdin.readline

def main():
    T = int(input())
    out = []
    for _ in range(T):
        n = int(input())
        song = sorted(map(int, input().split()))
        liao = sorted(map(int, input().split()))
        victories = 0
        enemy_ptr = 0
        for s in song:
            if s > liao[enemy_ptr]:
                victories += 1
                enemy_ptr += 1
        out.append("YES" if victories > n // 2 else "NO")
    sys.stdout.write('\n'.join(out) + '\n')

main()

第二题:背包排序

题目

玩家小 A 现在有一个 n × m 格子的背包(n 为高,m 为宽),有 k 个物品,先按排序算法把物品进行排序,然后根据排序后的物品依次放入背包。

在放入背包时,优先选择行数最小的位置进行放置,其次选择列数最小的位置。如果当前行无法容纳物品,则继续查找下一行。如果整个背包都无法放下该物品,则跳过该物品。

最后输出背包是否放得下所有物品,并输出当前背包状态,用 id 表示当前背包格子是什么物品,如果当前格子没有物品输出 0

每个物品都包含以下这些属性:

  • id:物品唯一 ID,每个物品各不相同。
  • height, width:物品占用的格子数(height 为高,width 为宽)。物品不可以旋转放入背包。
  • quality:物品的品质。数值越大品质越高。
  • type:物品的种类。

排序规则如下:

  1. 优先按照 type 排序:"equip" < "weapon" < "item" < "other"
  2. 品质高的优先
  3. id 小的优先

输入描述

第一行包含三个整数 n、m、k,分别表示背包的高、背包的宽、物品的数量。

接下来 k 行,每行包含四个整数 id、height、width、quality,以及一个字符串 type(type ∈ {"equip", "weapon", "item", "other"}),为物品包含的属性。

输出描述

第一行包含一个字符串 "YES" 表示背包可以放下所有物品,"NO" 表示有的物品放不进去背包。

接下来 n 行,每行包含 m 个整数,表示当前格子放着的物品 id,如果当前格子没有物品则输出 0

样例输入 1

4 3 3
1 1 3 7 other
2 3 1 2 equip
3 2 2 4 other

样例输出 1

YES
2 3 3
2 3 3
2 0 0
1 1 1

说明: 排序后顺序:2、3、1。按顺序放入即可。

样例输入 2

4 4 6
6 2 1 3 weapon
1 2 3 1 equip
3 2 1 4 item
5 3 3 3 weapon
2 2 2 3 other
4 2 1 3 item

样例输出 2

NO
1 1 1 6
1 1 1 6
3 4 2 2
3 4 2 2

参考题解

解题思路:

该程序采用贪心算法结合自定义排序规则。首先根据题目要求的优先级(种类权重 > 品质降序 > ID 升序)对所有物品进行预排序。随后遍历排序后的物品列表,在二维网格中按照"从上到下、从左到右"的顺序寻找第一个能够容纳该物品尺寸的空置区域。一旦找到合法位置,立即将其放置并填充 ID。若遍历整个网格均无法放置,则跳过该物品并标记最终状态为失败(NO)。

C++:

#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;

struct Product {
    int sn, rLen, cLen, score, level;
    string category;
};

int typeLevel(const string& cat) {
    if (cat == "equip") return 1;
    if (cat == "weapon") return 2;
    if (cat == "item") return 3;
    return 4; // other
}

bool cmp(const Product& a, const Product& b) {
    if (a.level != b.level) return a.level < b.level;
    if (a.score != b.score) return a.score > b.score;
    return a.sn < b.sn;
}

bool checkSpace(vector<vector<int>>& board, int x, int y, int h, int w) {
    for (int i = x; i < x + h; i++)
        for (int j = y; j < y + w; j++)
            if (board[i][j] != 0) return false;
    return true;
}

void markMatrix(vector<vector<int>>& board, int x, int y, int h, int w, int val) {
    for (int i = x; i < x + h; i++)
        for (int j = y; j < y + w; j++)
            board[i][j] = val;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    int rowMax, colMax, total;
    cin >> rowMax >> colMax >> total;
    vector<Product> list(total);
    for (int i = 0; i < total; i++) {
        cin >> list[i].sn >> list[i].rLen >> list[i].cLen >> list[i].score >> list[i].category;
        list[i].level = typeLevel(list[i].category);
    }
    sort(list.begin(), list.end(), cmp);
    vector<vector<int>> mat(rowMax, vector<int>(colMax, 0));
    bool success = true;
    for (const auto& p : list) {
        bool placed = false;
        // 优先遍历行,其次遍历列
        for (int i = 0; i <= rowMax - p.rLen && !placed; i++) {
            for (int j = 0; j <= colMax - p.cLen; j++) {
                if (checkSpace(mat, i, j, p.rLen, p.cLen)) {
                    markMatrix(mat, i, j, p.rLen, p.cLen, p.sn);
                    placed = true;
                    break;
                }
            }
        }
        if (!placed) success = false;
    }
    cout << (success ? "YES" : "NO") << "\n";
    for (int i = 0; i < rowMax; i++) {
        for (int j = 0; j < colMax; j++) {
            cout << mat[i][j] << (j == colMax - 1 ? "" : " ");
        }
        cout << "\n";
    }
    return 0;
}

Java:

import java.util.*;
import java.io.*;

public class Main {
    static class Product implements Comparable<Product> {
        int sn, rLen, cLen, score, level;
        String category;

        public Product(int sn, int rLen, int cLen, int score, String category) {
            this.sn = sn;
            this.rLen = rLen;
            this.cLen = cLen;
            this.score = score;
            this.category = category;
            // 映射类型权重
            switch (category) {
                case "equip": this.level = 1; break;
                case "weapon": this.level = 2; break;
                case "item": this.level = 3; break;
                default: this.level = 4; break;
            }
        }

        @Override
        public int compareTo(Product other) {
            if (this.level != other.level) return Integer.compare(this.level, other.level);
            if (this.score != other.score) return Integer.compare(other.score, this.score);
            return Integer.compare(this.sn, other.sn);
        }
    }

    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        if (!cin.hasNextInt()) return;
        int rowMax = cin.nextInt();
        int colMax = cin.nextInt();
        int total = cin.nextInt();
        List<Product> cargoList = new ArrayList<>();
        for (int i = 0; i < total; i++) {
            cargoList.add(new Product(cin.nextInt(), cin.nextInt(), cin.nextInt(),
                    cin.nextInt(), cin.next()));
        }
        Collections.sort(cargoList);
        int[][] mat = new int[rowMax][colMax];
        boolean success = true;
        for (Product p : cargoList) {
            boolean isPlaced = false;
            // 优先遍历行,其次遍历列
            for (int i = 0; i <= rowMax - p.rLen; i++) {
                for (int j = 0; j <= colMax - p.cLen; j++) {
                    if (checkSpace(mat, i, j, p.rLen, p.cLen)) {
                        markMatrix(mat, i, j, p.rLen, p.cLen, p.sn);
                        isPlaced = true;
                        break;
                    }
                }
                if (isPlaced) break;
            }
            if (!isPlaced) success = false;
        }
        System.out.println(success ? "YES" : "NO");
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < rowMax; i++) {
            for (int j = 0; j < colMax; j++) {
                sb.append(mat[i][j]).append(j == colMax - 1 ? "" : " ");
            }
            sb.append("\n");
        }
        System.out.print(sb.toString());
    }

    private static boolean checkSpace(int[][] board, int x, int y, int h, int w) {
        for (int i = x; i < x + h; i++) {
            for (int j = y; j < y + w; j++) {
                if (board[i][j] != 0) return false;
            }
        }
        return true;
    }

    private static void markMatrix(int[][] board, int x, int y, int h, int w, int val) {
        for (int i = x; i < x + h; i++) {
            for (int j = y; j < y + w; j++) {
                board[i][j] = val;
            }
        }
    }
}

Python:

import sys

def main():
    data = sys.stdin.read().split()
    idx = 0
    rowMax = int(data[idx]); idx += 1
    colMax = int(data[idx]); idx += 1
    total = int(data[idx]); idx += 1

    type_level = {"equip": 1, "weapon": 2, "item": 3, "other": 4}
    products = []
    for _ in range(total):
        sn = int(data[idx]); idx += 1
        rLen = int(data[idx]); idx += 1
        cLen = int(data[idx]); idx += 1
        score = int(data[idx]); idx += 1
        category = data[idx]; idx += 1
        level = type_level.get(category, 4)
        # 排序键:(type权重升序, 品质降序, id升序)
        products.append((level, -score, sn, rLen, cLen))

    products.sort()
    mat = [[0] * colMax for _ in range(rowMax)]
    success = True

    def check_space(x, y, h, w):
        for i in range(x, x + h):
            for j in range(y, y + w):
                if mat[i][j] != 0:
                    return False
        return True

    def mark_matrix(x, y, h, w, val):
        for i in range(x, x + h):
            for j in range(y, y + w):
                mat[i][j] = val

    for level, neg_score, sn, rLen, cLen in products:
        placed = False
        # 优先遍历行,其次遍历列
        for i in range(rowMax - rLen + 1):
            if placed:
                break
            for j in range(colMax - cLen + 1):
                if check_space(i, j, rLen, cLen):
                    mark_matrix(i, j, rLen, cLen, sn)
                    placed = True
                    break
        if not placed:
            success = False

    out = ["YES" if success else "NO"]
    for i in range(rowMax):
        out.append(" ".join(str(mat[i][j]) for j in range(colMax)))
    sys.stdout.write('\n'.join(out) + '\n')

main()

第三题:不朽荣光

题目

在《永劫无间》的决赛圈中,作为仅存的侠客之一,你正处于"聚窟洲"的一处狭长索桥上与其余敌方侠客对峙。

此时"暗域"(毒圈)已经严重蔓延,索桥的左端(坐标 ≤ 0)与右端(坐标 ≥ L)均已被高浓度的暗域覆盖,任何侠客一旦进入暗域范围就会因体力耗尽被瞬间淘汰。

令索桥的安全区域左侧边缘对应坐标 0,右侧边缘对应坐标 L。当前桥上还有 n 名敌方侠客,其初始坐标为 x_i,同一位置上可能有多名侠客,但均满足 0 < x_i < L,即暂时处于安全区内。

你捡到了一把金色品质的"火炮",并装备了稀有魂玉"连珠·反弹"。你可以向索桥上任意一个整数坐标点 p 发射一枚具有强力冲击波的炮弹,产生如下效果:

  1. 命中:如果某名敌方侠客当前坐标恰好为 p,则被炮弹直接命中造成巨额伤害淘汰;
  2. 左击退:如果某名敌方侠客当前坐标为 x 且 x < p,则会被爆炸气浪向左震飞 r 个单位,变为坐标 x - r;
  3. 右击退:如果某名敌方侠客当前坐标为 x 且 x > p,则会被爆炸气浪向右震飞 r 个单位,变为坐标 x + r。

当敌方侠客的坐标被震飞至 ≤ 0 或 ≥ L 时,就会跌入暗域被淘汰。

为了拿下"不朽荣光"成就(在另外两名队友已经阵亡的情况下,独自存活至少 1 分钟并最终获胜),你需要计算至少发射多少次炮弹,才能将所有敌方侠客淘汰?每次开火前,你都可以根据当前幸存敌人的位置,重新选择最优的落点 p。

输入描述

  • 第一行输入三个整数 n、L、r,分别表示敌方侠客数量、索桥安全区长度与震飞距离;
  • 第二行输入 n 个整数 x_i,表示初始时每名敌方侠客的坐标。

样例输入 1

3 10 2
3 5 9

样例输出 1

2

说明: 一种最优策略:第一次瞄准 5 处开火,直接淘汰坐标 5 的敌人,其余敌人被震飞至坐标 1(3-2,存活)和 11(9+2,掉入暗域淘汰);第二次瞄准 1 处开火,淘汰剩余敌人。

样例输入 2

5 20 3
2 6 9 12 17

样例输出 2

2

说明: 一种最优策略:第一次瞄准 9 处开火,直接淘汰坐标 9 的敌人,其余被震飞至 -1、3、15、20,其中 -1 和 20 触发暗域淘汰;第二次瞄准 3 处开火,直接淘汰坐标 3 的敌人,另一名被震飞至 18(15+3,掉入暗域淘汰)。

参考题解

解题思路:

本题采用排序去重 + 二分答案的算法思路。因为发射的炮弹越多,越容易淘汰所有敌人(结果具有单调性),所以我们可以通过二分查找来确定最少的射击次数 k。同一位置的敌人受气浪影响完全一致,因此预先进行去重处理。

在验证 k 次射击是否足够时,采用贪心策略:从左到右遍历敌人,对于当前敌人,贪心地假设前面已经不得不消耗的 need 次射击都在其左侧(产生向右的推力),而剩余的 (k - need) 次射击全在其右侧(产生向左的推力)。如果在这种最有利于将其向左震飞的极限情况下,该敌人仍留在安全区内(0 < 最终位置 < L),则说明必须额外消耗一次射击来处理他,令 need 加 1。若中途 need 超过了 k,则说明 k 发炮弹不够。

核心递推公式:pos = x + (2 * need - k) * r

C++:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;

ll L, r;
vector<ll> a;

// 检查给定的射击总次数 k 是否足够
bool check(ll k) {
    ll need = 0; // 记录必须使用的直接/左侧射击次数
    for (ll x : a) {
        // 假设已用的 need 次射击都在左侧,剩下的 (k - need) 次都在右侧
        ll pos = x + (2LL * need - k) * r;
        // 如果在此极限情况下仍处于安全区内,则必须额外开一炮
        if (pos > 0 && pos < L) {
            need++;
         

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

2025 春招笔试合集 文章被收录于专栏

2025打怪升级记录,大厂笔试合集 C++, Java, Python等多种语言做法集合指南

全部评论

相关推荐

评论
3
4
分享

创作者周榜

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