【笔试题汇总】华为春招笔试题解 2024-4-17

时间:2024-05-01 07:01:20

这里是paoxiaomo,一个现役ACMer,之后将会持续更新算法笔记系列以及笔试题题解系列
本文章面向想打ICPC/蓝桥杯/天梯赛等程序设计竞赛,以及各个大厂笔试的选手
感谢大家的订阅➕ 和 喜欢????
有什么想看的算法专题可以私信博主

(本文题面由清隆学长收集)

01.扑克牌消消乐

题目描述

K小姐最近沉迷于一款扑克牌消除游戏。游戏规则如下:从一副扑克牌中随机抽取 n n n 张牌组成一个序列,如果有连续的 3 3 3 张相同牌号的卡牌,则这 3 3 3 张卡牌可以消除。消除后,剩余卡牌按照当前顺序重新合并成新的序列,继续寻找可以消除的卡牌组合,直到无法再消除为止。

需要注意的是,如果存在连续的 4 4 4 张相同牌号的卡牌,在消除后会剩余 1 1 1 张该牌号的卡牌。

现在,K小姐想知道最后剩余的卡牌序列是什么样的,你能帮助她吗?

输入格式

第一行包含一个正整数 n n n 1 ≤ n ≤ 52 1 \leq n \leq 52 1n52),表示抽取的卡牌数量。

第二行包含 n n n 个以空格分隔的字符串,表示抽取的卡牌序列,卡牌号仅包含 2 2 2- 10 10 10 A A A J J J Q Q Q K K K

输出格式

输出一个字符串,表示最终剩余的卡牌号序列,卡牌号之间以空格分隔。如果最终没有卡牌剩余,则输出 0 0 0

样例输入

10
3 A 2 2 2 A A 7 7 7

样例输出

3

数据范围

  • 1 ≤ n ≤ 52 1 \leq n \leq 52 1n52
  • 卡牌号仅包含 2 2 2- 10 10 10 A A A J J J Q Q Q K K K

【题目解析】

  1. 读取输入,包括卡牌数量 n n n n n n 张卡牌序列。
  2. 定义一个函数 removeTriples,用于消除连续 3 3 3 张相同牌号的卡牌,并返回消除后的卡牌序列。
  3. 进入主循环,不断调用 removeTriples 函数直到无法再消除为止,即当前序列与上一次序列相同。
  4. 输出最终剩余的卡牌序列,如果没有剩余卡牌则输出 “0”。

其中 removeTriples 函数负责消除连续 3 3 3 张相同牌号的卡牌:

cpp

#include <iostream>
#include <string>
#include <vector>

using namespace std;

string removeTriples(const string& cards) {
    string result = "";
    int len = cards.length();
    int i = 0;
    while (i < len) {
        int j = i;
        while (j < len && cards[j] == cards[i]) {
            j++;
        }
        if (j - i >= 3) {
            i = j;
        } else {
            result += cards.substr(i, j - i);
            i = j;
        }
    }
    return result;
}

int main() {
    int n;
    cin >> n;
    vector<string> cards(n);
    for (int i = 0; i < n; ++i) {
        cin >> cards[i];
    }

    string current = "";
    for (int i = 0; i < n; ++i) {
        current += cards[i];
    }

    string prev = "";
    while (prev != current) {
        prev = current;
        current = removeTriples(current);
    }

    if (current.empty()) {
        cout << "0" << endl;
    } else {
        for (char c : current) {
            cout << c << " ";
        }
        cout << endl;
    }

    return 0;
}

02.公司部门风险评估

题目描述

LYA 是一家大型科技公司的风险评估师。公司的部门结构可以看作一棵树,每个部门在评估前都有一些尚未解决的问题。部门的风险值可以用来评估该部门是否存在风险,风险值的计算公式为: 风险值 = 5 × 严重问题数 + 2 × 一般问题数 风险值 = 5 \times 严重问题数 + 2 \times 一般问题数 风险值=5×严重问题数+2×一般问题数

其中,每个部门的不同级别问题数量需要将该部门及其下属部门的相应级别问题数量求和。当部门的风险值小于等于给定的阈值时,该部门被认为是安全的;否则,该部门被视为风险部门,需要进一步整改。

现在给出公司的部门结构以及各部门的问题数量,请你帮助 LYA 计算出风险部门的数量。

输入格式

第一行包含两个正整数 M M M N N N 1 ≤ M ≤ 100000 1 \leq M \leq 100000 1M100000 1 ≤ N ≤ 1000 1 \leq N \leq 1000 1N1000),分别表示风险阈值和部门的数量。

接下来 N N N 行,每行包含四个字段,用空格分隔:

  • 第一个字段为部门名称 A i A_i Ai
  • 第二个字段为 A i A_i Ai 的上级部门名称 B i B_i Bi,如果 A i A_i Ai 为公司的最高层部门,则 B i B_i Bi* 表示;
  • 第三个字段为问题级别 C i C_i Ci C i ∈ { 0 , 1 } C_i \in \{0, 1\} Ci{0,1},其中 0 0 0 表示严重问题, 1 1 1 表示一般问题);
  • 第四个字段为该部门该级别的问题数量 D i D_i Di 1 ≤ D i ≤ 1000 1 \leq D_i \leq 1000 1Di1000)。

其中, A i A_i Ai B i B_i Bi 为由小写英文字母组成的字符串,长度不超过 5 5 5

输入保证部门结构为一棵树,不会出现环的情况。

输出格式

输出一个整数,表示风险部门的数量。

样例输入

40 12
a * 0 2
a * 1 2
b a 0 3
b a 1 5
c a 1 3
d a 0 1
d a 1 3
e b 0 2
f * 0 8
f * 1 10
g f 1 2
h * 0 4

样例输出

2

数据范围

  • 1 ≤ M ≤ 100000 1 \leq M \leq 100000 1M100000
  • 1 ≤ N ≤ 1000 1 \leq N \leq 1000 1N1000
  • 1 ≤ D i ≤ 1000 1 \leq D_i \leq 1000 1Di1000
  • A i A_i Ai B i B_i Bi 为由小写英文字母组成的字符串,长度不超过 5 5 5

【题目解析】

  1. 读取输入,包括风险阈值和部门数量,并构建部门树结构。
  2. 对每个部门,计算其风险值,如果风险值大于阈值,则该部门及其下属部门都被标记为风险部门。
  3. 统计所有被标记的部门数量,即为风险部门的数量。
  4. 输出风险部门的数量。

cpp

#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>

using namespace std;

struct Department {
    string name;
    string parent;
    int severe_issues;
    int normal_issues;
    vector<string> children;
};

unordered_map<string, Department> departments;

// Function to calculate the risk value of a department
int calculateRisk(const string& department_name, int threshold) {
    Department& dept = departments[department_name];
    int risk_value = 5 * dept.severe_issues + 2 * dept.normal_issues;
    if (risk_value > threshold) {
        return 1;
    } else {
        int total_risk = 0;
        for (const string& child_name : dept.children) {
            total_risk += calculateRisk(child_name, threshold);
        }
        return total_risk;
    }
}

int main() {
    int threshold, num_departments;
    cin >> threshold >> num_departments;

    for (int i = 0; i < num_departments; ++i) {
        string name, parent;
        int issue_type, num_issues;
        cin >> name >> parent >> issue_type >> num_issues;
        departments[name] = {name, parent, 0, 0};
        if (issue_type == 0) {
            departments[name].severe_issues = num_issues;
        } else {
            departments[name].normal_issues = num_issues;
        }
        if (parent != "*") {
            departments[parent].children.push_back(name);
        }
    }

    int risk_departments = calculateRisk("*", threshold);
    cout << risk_departments << endl;

    return 0;
}

03.城市应急疏散

题目描述

LYA 是一名城市应急管理专家,她负责制定城市在发生重大事故时的疏散计划。城市由 n n n 个区域组成,每个区域之间都有道路相连。当某个区域发生事故需要疏散时,LYA 需要选择一个或多个安全区域作为疏散目的地,并确保疏散路径的总长度最短。

给定一个 n × n n \times n n×n 的矩阵 d i s t dist dist,其中 d i s t [ i ] [ j ] dist[i][j] dist[i][j] 表示区域 i i i 到区域 j j j 的道路长度,如果 d i s t [ i ] [ j ] = − 1 dist[i][j] = -1 dist[i][j]=1,则表示区域 i i i 和区域 j j j 之间没有直接相连的道路。另外,每个区域还有一个剩余容量 c a p [ i ] cap[i] cap[i],表示该区域最多可以容纳的人数。

当某个区域 x x x 发生事故需要疏散人数为 p p p 时,请你帮助 LYA 选择疏散区域,使得疏散路径的总长度最短,并且疏散区域的剩余容量之和不小于 p p p