【2024年华为OD机试】 (C卷,200分)- 贪心歌手(JavaScriptJava PythonC/C++)
一、问题描述
问题描述
一个歌手需要从A城前往B城参加演出,必须在T天内到达。途中会经过N座城市,且不能往回走。每两座城市之间的行程天数已知。歌手在每座城市都可以卖唱赚钱,但收入会随着停留天数的增加而递减。具体来说,第一天赚M元,第二天赚M-D元,第三天赚M-2D元,依此类推,直到收入不再减少(即收入不低于0)。歌手到达某座城市的第二天才能开始卖唱,且如果今天卖唱,第二天才能出发。
目标是规划歌手的行程,使得在T天内赚取的总收入最大。
输入输出
-
输入:
- 第一行:T(总天数)和N(途经城市数)。
- 第二行:N+1个数字,表示每两座城市之间的行程天数。
- 接下来N行:每行两个数字M和D,表示每座城市的卖唱收入预期。
-
输出:
- 一个数字,表示歌手最多可以赚多少钱。
解题思路
-
计算可用时间:
- 首先计算所有行程天数的总和
roadCost
,这是必须花费的时间。 - 剩余可用于卖唱的时间为
remain = T - roadCost
。
- 首先计算所有行程天数的总和
-
收入计算:
- 每座城市的收入是递减的,第一天赚M元,第二天赚M-D元,依此类推,直到收入不再减少。
- 因此,每座城市的收入可以表示为一个等差数列。
-
时间分配:
- 需要将
remain
天合理分配给各座城市,以最大化总收入。 - 由于收入递减,优先选择收入较高的天数。
- 需要将
-
优先队列的使用:
- 使用优先队列(最小堆)来记录已经分配的天数中收入最小的天数。
- 当需要分配新的天数时,比较当前城市的收入与优先队列中的最小收入,如果当前收入更高,则替换。
具体步骤
-
初始化:
- 计算
remain
。 - 初始化优先队列。
- 计算
-
遍历城市:
- 对于每座城市,计算在该城市停留不同天数的收入。
- 将收入较高的天数加入优先队列。
-
替换策略:
- 如果优先队列已满(即所有
remain
天已分配),则比较当前城市的收入与优先队列中的最小收入。 - 如果当前收入更高,则替换。
- 如果优先队列已满(即所有
-
计算总收入:
- 最终,优先队列中的所有收入之和即为最大总收入。
示例解析
以题目中的示例为例:
-
输入:
- T = 10,N = 2
- 行程天数:1, 1, 2
- 城市1:M = 120,D = 20
- 城市2:M = 90,D = 10
-
计算:
roadCost
= 1 + 1 + 2 = 4remain
= 10 - 4 = 6
-
分配:
- 城市1:停留3天,收入为120 + 100 + 80 = 300
- 城市2:停留3天,收入为90 + 80 + 70 = 240
- 总收入 = 300 + 240 = 540
通过合理分配时间,歌手可以在6天内赚取540元,这是最优的收入。
总结
本题的关键在于合理分配剩余时间,使得总收入最大化。通过使用优先队列来动态调整收入分配,可以有效地找到最优解。
二、JavaScript算法源码
以下是对代码的详细注释和讲解,帮助理解每一部分的逻辑和实现方式:
代码结构
-
输入处理:
- 使用
readline
模块读取输入数据。 - 解析总天数
t
和城市数量n
。 - 解析每两座城市之间的行程天数,并计算总行程时间
roadCost
。 - 解析每座城市的卖唱收入预期
m
和递减值d
,存储在数组mds
中。
- 使用
-
剩余时间计算:
- 计算剩余可用于卖唱的时间
remain = t - roadCost
。 - 如果
remain <= 0
,说明没有时间可用于卖唱,直接输出0
并结束程序。
- 计算剩余可用于卖唱的时间
-
优先队列的使用:
- 使用数组
pq
模拟优先队列(降序排序),记录每天赚的钱。 - 遍历每座城市,计算在该城市停留每天的收入,并尝试将其加入优先队列。
- 使用数组
-
收入计算与替换策略:
- 对于每座城市,只要当天收入
m > 0
,就继续计算。 - 如果优先队列已满(即
pq.length >= remain
),则比较当前收入m
与优先队列中最小收入pq.at(-1)
:- 如果
m > pq.at(-1)
,说明当前收入更高,替换掉优先队列中最小收入。 - 否则,停止在该城市停留,因为继续停留收入会更低。
- 如果
- 将当前收入
m
加入优先队列,并对队列重新排序(降序)。 - 每天收入减少
d
,继续计算下一天的收入。
- 对于每座城市,只要当天收入
-
输出结果:
- 计算优先队列中所有收入的总和,输出最大总收入。
代码逐行注释
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;void (async function () {// 读取总天数t和城市数量nconst [t, n] = (await readline()).split(" ").map(Number);// 读取每两座城市之间的行程天数,并计算总行程时间roadCostconst roadCost = (await readline()).split(" ").map(Number).reduce((a, b) => a + b);// 读取每座城市的卖唱收入预期m和递减值d,存储在数组mds中const mds = [];for (let i = 0; i < n; i++) {mds.push((await readline()).split(" ").map(Number));}// 计算剩余可用于卖唱的时间remainconst remain = t - roadCost;// 如果没有剩余时间,直接输出0并结束if (remain <= 0) {console.log(0);return;}// 优先队列(降序数组),记录每天赚的钱const pq = [];// 遍历每座城市for (let [m, d] of mds) {// 只要在当前城市还有钱赚(m > 0),就继续停留while (m > 0) {// 如果优先队列已满(即已经分配了remain天)if (pq.length >= remain) {// 比较当前收入m与优先队列中最小收入pq.at(-1)if (m > pq.at(-1)) {// 如果当前收入更高,替换掉优先队列中最小收入pq.pop();} else {// 如果当前收入更低,停止在该城市停留break;}}// 将当前收入m加入优先队列pq.push(m);// 对优先队列重新排序(降序)pq.sort((a, b) => b - a);// 每天收入减少dm -= d;}}// 计算优先队列中所有收入的总和const ans = pq.reduce((a, b) => a + b);// 输出最大总收入console.log(ans);
})();
代码逻辑详解
-
输入处理:
- 使用
readline
模块逐行读取输入数据。 - 将总天数
t
和城市数量n
解析为数字。 - 将每两座城市之间的行程天数解析为数组,并计算总行程时间
roadCost
。 - 将每座城市的卖唱收入预期
m
和递减值d
解析为数组,存储在mds
中。
- 使用
-
剩余时间计算:
- 计算剩余可用于卖唱的时间
remain = t - roadCost
。 - 如果
remain <= 0
,说明没有时间可用于卖唱,直接输出0
并结束程序。
- 计算剩余可用于卖唱的时间
-
优先队列的使用:
- 使用数组
pq
模拟优先队列,记录每天赚的钱。 - 遍历每座城市,计算在该城市停留每天的收入,并尝试将其加入优先队列。
- 使用数组
-
收入计算与替换策略:
- 对于每座城市,只要当天收入
m > 0
,就继续计算。 - 如果优先队列已满(即
pq.length >= remain
),则比较当前收入m
与优先队列中最小收入pq.at(-1)
:- 如果
m > pq.at(-1)
,说明当前收入更高,替换掉优先队列中最小收入。 - 否则,停止在该城市停留,因为继续停留收入会更低。
- 如果
- 将当前收入
m
加入优先队列,并对队列重新排序(降序)。 - 每天收入减少
d
,继续计算下一天的收入。
- 对于每座城市,只要当天收入
-
输出结果:
- 计算优先队列中所有收入的总和,输出最大总收入。
示例运行
输入:
10 2
1 1 2
120 20
90 10
运行过程:
- 计算总行程时间
roadCost = 1 + 1 + 2 = 4
。 - 计算剩余时间
remain = 10 - 4 = 6
。 - 遍历城市:
- 城市1:收入
120, 100, 80
,加入优先队列[120, 100, 80]
。 - 城市2:收入
90, 80, 70
,替换优先队列中的最小收入80
,最终队列为[120, 100, 90, 80, 70]
。
- 城市1:收入
- 计算总收入
120 + 100 + 90 + 80 + 70 = 540
。
输出:
540
总结
代码通过优先队列动态调整收入分配,确保在有限的时间内赚取最大收入。逻辑清晰,注释详细,适合理解贪心算法的应用场景。
三、Java算法源码
以下是Java代码的详细注释和讲解,帮助理解每一部分的逻辑和实现方式:
代码结构
-
输入处理:
- 使用
Scanner
读取输入数据。 - 解析总天数
t
和城市数量n
。 - 解析每两座城市之间的行程天数,并计算总行程时间
roadCost
。 - 解析每座城市的卖唱收入预期
m
和递减值d
,存储在二维数组mds
中。
- 使用
-
剩余时间计算:
- 计算剩余可用于卖唱的时间
remain = t - roadCost
。 - 如果
remain <= 0
,说明没有时间可用于卖唱,直接返回0
。
- 计算剩余可用于卖唱的时间
-
优先队列的使用:
- 使用
PriorityQueue
(小顶堆)记录每天赚的钱。 - 遍历每座城市,计算在该城市停留每天的收入,并尝试将其加入优先队列。
- 使用
-
收入计算与替换策略:
- 对于每座城市,只要当天收入
m > 0
,就继续计算。 - 如果优先队列已满(即
pq.size() >= remain
),则比较当前收入m
与优先队列中最小收入pq.peek()
:- 如果
m > pq.peek()
,说明当前收入更高,替换掉优先队列中最小收入。 - 否则,停止在该城市停留,因为继续停留收入会更低。
- 如果
- 将当前收入
m
加入优先队列。 - 每天收入减少
d
,继续计算下一天的收入。
- 对于每座城市,只要当天收入
-
输出结果:
- 计算优先队列中所有收入的总和,返回最大总收入。
代码逐行注释
import java.util.PriorityQueue;
import java.util.Scanner;public class Main {static int t; // 总天数static int n; // 城市数量static int roadCost; // 总行程时间static int[][] mds; // 每座城市的卖唱收入预期public static void main(String[] args) {Scanner sc = new Scanner(System.in);// 读取总天数t和城市数量nt = sc.nextInt();n = sc.nextInt();// 读取每两座城市之间的行程天数,并计算总行程时间roadCostroadCost = 0;for (int i = 0; i < n + 1; i++) {roadCost += sc.nextInt();}// 读取每座城市的卖唱收入预期m和递减值d,存储在二维数组mds中mds = new int[n][2];for (int i = 0; i < n; i++) {mds[i][0] = sc.nextInt(); // mmds[i][1] = sc.nextInt(); // d}// 输出最大总收入System.out.println(getResult());}public static int getResult() {// 计算剩余可用于卖唱的时间remainint remain = t - roadCost;// 如果没有剩余时间,直接返回0if (remain <= 0) {return 0;}// 优先队列(小顶堆),记录每天赚的钱PriorityQueue<Integer> pq = new PriorityQueue<>((a, b) -> a - b);// 遍历每座城市for (int[] md : mds) {// 第一天卖唱可以赚m,后续每天的收入会减少dint m = md[0];int d = md[1];// 只要在当前城市还有钱赚(m > 0),就继续停留while (m > 0) {// 如果优先队列已满(即已经分配了remain天)if (pq.size() >= remain) {// 比较当前收入m与优先队列中最小收入pq.peek()if (m > pq.peek()) {// 如果当前收入更高,替换掉优先队列中最小收入pq.poll();} else {// 如果当前收入更低,停止在该城市停留break;}}// 将当前收入m加入优先队列pq.add(m);// 每天收入减少dm -= d;}}// 计算优先队列中所有收入的总和return pq.stream().reduce(Integer::sum).orElse(0);}
}
代码逻辑详解
-
输入处理:
- 使用
Scanner
读取输入数据。 - 解析总天数
t
和城市数量n
。 - 解析每两座城市之间的行程天数,并计算总行程时间
roadCost
。 - 解析每座城市的卖唱收入预期
m
和递减值d
,存储在二维数组mds
中。
- 使用
-
剩余时间计算:
- 计算剩余可用于卖唱的时间
remain = t - roadCost
。 - 如果
remain <= 0
,说明没有时间可用于卖唱,直接返回0
。
- 计算剩余可用于卖唱的时间
-
优先队列的使用:
- 使用
PriorityQueue
(小顶堆)记录每天赚的钱。 - 遍历每座城市,计算在该城市停留每天的收入,并尝试将其加入优先队列。
- 使用
-
收入计算与替换策略:
- 对于每座城市,只要当天收入
m > 0
,就继续计算。 - 如果优先队列已满(即
pq.size() >= remain
),则比较当前收入m
与优先队列中最小收入pq.peek()
:- 如果
m > pq.peek()
,说明当前收入更高,替换掉优先队列中最小收入。 - 否则,停止在该城市停留,因为继续停留收入会更低。
- 如果
- 将当前收入
m
加入优先队列。 - 每天收入减少
d
,继续计算下一天的收入。
- 对于每座城市,只要当天收入
-
输出结果:
- 计算优先队列中所有收入的总和,返回最大总收入。
示例运行
输入:
10 2
1 1 2
120 20
90 10
运行过程:
- 计算总行程时间
roadCost = 1 + 1 + 2 = 4
。 - 计算剩余时间
remain = 10 - 4 = 6
。 - 遍历城市:
- 城市1:收入
120, 100, 80
,加入优先队列[120, 100, 80]
。 - 城市2:收入
90, 80, 70
,替换优先队列中的最小收入80
,最终队列为[120, 100, 90, 80, 70]
。
- 城市1:收入
- 计算总收入
120 + 100 + 90 + 80 + 70 = 540
。
输出:
540
总结
代码通过优先队列动态调整收入分配,确保在有限的时间内赚取最大收入。逻辑清晰,注释详细,适合理解贪心算法的应用场景。
四、Python算法源码
以下是Python代码的详细注释和讲解,帮助理解每一部分的逻辑和实现方式:
代码结构
-
输入处理:
- 使用
input()
读取输入数据。 - 解析总天数
t
和城市数量n
。 - 解析每两座城市之间的行程天数,并计算总行程时间
roadCost
。 - 解析每座城市的卖唱收入预期
m
和递减值d
,存储在列表mds
中。
- 使用
-
剩余时间计算:
- 计算剩余可用于卖唱的时间
remain = t - roadCost
。 - 如果
remain <= 0
,说明没有时间可用于卖唱,直接返回0
。
- 计算剩余可用于卖唱的时间
-
优先队列的使用:
- 使用
heapq
模块实现小顶堆,记录每天赚的钱。 - 遍历每座城市,计算在该城市停留每天的收入,并尝试将其加入优先队列。
- 使用
-
收入计算与替换策略:
- 对于每座城市,只要当天收入
m > 0
,就继续计算。 - 如果优先队列已满(即
len(pq) >= remain
),则比较当前收入m
与优先队列中最小收入pq[0]
:- 如果
m > pq[0]
,说明当前收入更高,替换掉优先队列中最小收入。 - 否则,停止在该城市停留,因为继续停留收入会更低。
- 如果
- 将当前收入
m
加入优先队列。 - 每天收入减少
d
,继续计算下一天的收入。
- 对于每座城市,只要当天收入
-
输出结果:
- 计算优先队列中所有收入的总和,返回最大总收入。
代码逐行注释
import heapq# 输入获取
t, n = map(int, input().split()) # 读取总天数t和城市数量n
roadCost = sum(map(int, input().split())) # 读取行程天数并计算总行程时间roadCost
mds = [list(map(int, input().split())) for _ in range(n)] # 读取每座城市的m和d,存储在列表mds中# 算法入口
def getResult():# remain是刨去必要的路程时间后,剩余可以用于赚钱的时间remain = t - roadCost# 如果没有剩余时间,直接返回0if remain <= 0:return 0# 优先队列(小顶堆),记录每天赚的钱pq = []# 遍历每座城市for m, d in mds:# 只要在当前城市还有钱赚(m > 0),就继续停留while m > 0:# 如果优先队列已满(即已经分配了remain天)if len(pq) >= remain:# 比较当前收入m与优先队列中最小收入pq[0]if m > pq[0]:# 如果当前收入更高,替换掉优先队列中最小收入heapq.heappop(pq)else:# 如果当前收入更低,停止在该城市停留break# 将当前收入m加入优先队列heapq.heappush(pq, m)# 每天收入减少dm -= d# 计算优先队列中所有收入的总和return sum(pq)# 算法调用
print(getResult())
代码逻辑详解
-
输入处理:
- 使用
input()
读取输入数据。 - 解析总天数
t
和城市数量n
。 - 解析每两座城市之间的行程天数,并计算总行程时间
roadCost
。 - 解析每座城市的卖唱收入预期
m
和递减值d
,存储在列表mds
中。
- 使用
-
剩余时间计算:
- 计算剩余可用于卖唱的时间
remain = t - roadCost
。 - 如果
remain <= 0
,说明没有时间可用于卖唱,直接返回0
。
- 计算剩余可用于卖唱的时间
-
优先队列的使用:
- 使用
heapq
模块实现小顶堆,记录每天赚的钱。 - 遍历每座城市,计算在该城市停留每天的收入,并尝试将其加入优先队列。
- 使用
-
收入计算与替换策略:
- 对于每座城市,只要当天收入
m > 0
,就继续计算。 - 如果优先队列已满(即
len(pq) >= remain
),则比较当前收入m
与优先队列中最小收入pq[0]
:- 如果
m > pq[0]
,说明当前收入更高,替换掉优先队列中最小收入。 - 否则,停止在该城市停留,因为继续停留收入会更低。
- 如果
- 将当前收入
m
加入优先队列。 - 每天收入减少
d
,继续计算下一天的收入。
- 对于每座城市,只要当天收入
-
输出结果:
- 计算优先队列中所有收入的总和,返回最大总收入。
示例运行
输入:
10 2
1 1 2
120 20
90 10
运行过程:
- 计算总行程时间
roadCost = 1 + 1 + 2 = 4
。 - 计算剩余时间
remain = 10 - 4 = 6
。 - 遍历城市:
- 城市1:收入
120, 100, 80
,加入优先队列[120, 100, 80]
。 - 城市2:收入
90, 80, 70
,替换优先队列中的最小收入80
,最终队列为[120, 100, 90, 80, 70]
。
- 城市1:收入
- 计算总收入
120 + 100 + 90 + 80 + 70 = 540
。
输出:
540
总结
代码通过优先队列动态调整收入分配,确保在有限的时间内赚取最大收入。逻辑清晰,注释详细,适合理解贪心算法的应用场景。
五、C/C++算法源码:
以下是C语言和C++代码的实现,包含详细的中文注释和讲解:
C语言代码
#include <stdio.h>
#include <stdlib.h>// 比较函数,用于降序排序
int cmp(const void *a, const void *b) {return *((int *) b) - *((int *) a);
}int main() {int t, n;scanf("%d %d", &t, &n); // 读取总天数t和城市数量n// roadCost是A~B城市必需的路程时间int roadCost = 0;for (int i = 0; i < n + 1; i++) {int cost;scanf("%d", &cost); // 读取每段路程的时间roadCost += cost; // 累加总路程时间}// remain是刨去必要的路程时间后,剩余可以用于赚钱的时间int remain = t - roadCost;// 如果没有剩余时间可以用,则赚不到钱if (remain <= 0) {puts("0"); // 输出0return 0;}// 优先队列(降序数组)记录赚到的钱, 即数组尾巴是某天赚的最少的钱int pq[remain + 1]; // 数组模拟优先队列int pq_size = 0; // 优先队列的当前大小for (int i = 0; i < n; i++) {// 第一天卖唱可以赚m,后续每天的收入会减少dint m, d;scanf("%d %d", &m, &d); // 读取当前城市的m和d// 只要在当前城市还有钱赚,那么就继续待while (m > 0) {// 只有remain天可以赚钱,超出的时间不能赚钱,因此需要比较超出的时间赚的钱m,和前面时间中赚的最少的钱pq[pq_size - 1]if (pq_size >= remain) {// pq[pq_size - 1]只可能是某座城市停留的最后一天的赚的钱,因为每座城市都是停留的最后一天赚的钱最少if (m > pq[pq_size - 1]) {// 如果当前城市当天赚的钱m,比前面天里面赚的最少的pq[pq_size - 1]多,那么就赚pq[pq_size - 1]钱的那天时间节约下来,给当天用pq_size--; // 移除最小收入} else {// 如果当前城市当天赚的钱m,比前面天里面赚的最少的pq[pq_size - 1]还少,则当前城市继续待下去赚的钱只会更少,因此没必要呆下去了break;}}// 如果所有城市停留时间没有超出remain天,或者当天是超出的时间,但是比前面赚的最少的一天的赚的更多,则赚m更优pq[pq_size++] = m; // 将当前收入加入优先队列qsort(pq, pq_size, sizeof(int), cmp); // 对优先队列重新排序(降序)// 每天收入减少dm -= d;}}// 计算优先队列中所有收入的总和int ans = 0;for (int i = 0; i < pq_size; i++) {ans += pq[i];}// 输出最大总收入printf("%d\n", ans);return 0;
}
C++代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;// 比较函数,用于降序排序
bool cmp(int a, int b) {return a > b;
}int main() {int t, n;cin >> t >> n; // 读取总天数t和城市数量n// roadCost是A~B城市必需的路程时间int roadCost = 0;for (int i = 0; i < n + 1; i++) {int cost;cin >> cost; // 读取每段路程的时间roadCost += cost; // 累加总路程时间}// remain是刨去必要的路程时间后,剩余可以用于赚钱的时间int remain = t - roadCost;// 如果没有剩余时间可以用,则赚不到钱if (remain <= 0) {cout << 0 << endl; // 输出0return 0;}// 优先队列(降序数组)记录赚到的钱, 即数组尾巴是某天赚的最少的钱vector<int> pq; // 动态数组模拟优先队列for (int i = 0; i < n; i++) {// 第一天卖唱可以赚m,后续每天的收入会减少dint m, d;cin >> m >> d; // 读取当前城市的m和d// 只要在当前城市还有钱赚,那么就继续待while (m > 0) {// 只有remain天可以赚钱,超出的时间不能赚钱,因此需要比较超出的时间赚的钱m,和前面时间中赚的最少的钱pq.back()if (pq.size() >= remain) {// pq.back()只可能是某座城市停留的最后一天的赚的钱,因为每座城市都是停留的最后一天赚的钱最少if (m > pq.back()) {// 如果当前城市当天赚的钱m,比前面天里面赚的最少的pq.back()多,那么就赚pq.back()钱的那天时间节约下来,给当天用pq.pop_back(); // 移除最小收入} else {// 如果当前城市当天赚的钱m,比前面天里面赚的最少的pq.back()还少,则当前城市继续待下去赚的钱只会更少,因此没必要呆下去了break;}}// 如果所有城市停留时间没有超出remain天,或者当天是超出的时间,但是比前面赚的最少的一天的赚的更多,则赚m更优pq.push_back(m); // 将当前收入加入优先队列sort(pq.begin(), pq.end(), cmp); // 对优先队列重新排序(降序)// 每天收入减少dm -= d;}}// 计算优先队列中所有收入的总和int ans = 0;for (int val : pq) {ans += val;}// 输出最大总收入cout << ans << endl;return 0;
}
代码逻辑详解
-
输入处理:
- 读取总天数
t
和城市数量n
。 - 读取每段路程的时间,并计算总行程时间
roadCost
。 - 计算剩余可用于卖唱的时间
remain = t - roadCost
。
- 读取总天数
-
优先队列的实现:
- 使用数组(C语言)或
vector
(C++)模拟优先队列。 - 通过排序(降序)实现优先队列的功能。
- 使用数组(C语言)或
-
收入计算与替换策略:
- 对于每座城市,只要当天收入
m > 0
,就继续计算。 - 如果优先队列已满(即
pq.size() >= remain
),则比较当前收入m
与优先队列中最小收入pq.back()
:- 如果
m > pq.back()
,说明当前收入更高,替换掉优先队列中最小收入。 - 否则,停止在该城市停留,因为继续停留收入会更低。
- 如果
- 将当前收入
m
加入优先队列,并对队列重新排序(降序)。 - 每天收入减少
d
,继续计算下一天的收入。
- 对于每座城市,只要当天收入
-
输出结果:
- 计算优先队列中所有收入的总和,输出最大总收入。
示例运行
输入:
10 2
1 1 2
120 20
90 10
运行过程:
- 计算总行程时间
roadCost = 1 + 1 + 2 = 4
。 - 计算剩余时间
remain = 10 - 4 = 6
。 - 遍历城市:
- 城市1:收入
120, 100, 80
,加入优先队列[120, 100, 80]
。 - 城市2:收入
90, 80, 70
,替换优先队列中的最小收入80
,最终队列为[120, 100, 90, 80, 70]
。
- 城市1:收入
- 计算总收入
120 + 100 + 90 + 80 + 70 = 540
。
输出:
540
总结
- C语言和C++代码通过数组或
vector
模拟优先队列,动态调整收入分配,确保在有限的时间内赚取最大收入。 - 逻辑清晰,注释详细,适合理解贪心算法的应用场景。
六、尾言
什么是华为OD?
华为OD(Outsourcing Developer,外包开发工程师)是华为针对软件开发工程师岗位的一种招聘形式,主要包括笔试、技术面试以及综合面试等环节。尤其在笔试部分,算法题的机试至关重要。
为什么刷题很重要?
-
机试是进入技术面的第一关:
华为OD机试(常被称为机考)主要考察算法和编程能力。只有通过机试,才能进入后续的技术面试环节。 -
技术面试需要手撕代码:
技术一面和二面通常会涉及现场编写代码或算法题。面试官会注重考察候选人的思路清晰度、代码规范性以及解决问题的能力。因此提前刷题、多练习是通过面试的重要保障。 -
入职后的可信考试:
入职华为后,还需要通过“可信考试”。可信考试分为三个等级:- 入门级:主要考察基础算法与编程能力。
- 工作级:更贴近实际业务需求,可能涉及复杂的算法或与工作内容相关的场景题目。
- 专业级:最高等级,考察深层次的算法以及优化能力,与薪资直接挂钩。
刷题策略与说明:
2024年8月14日之后,华为OD机试的题库转为 E卷,由往年题库(D卷、A卷、B卷、C卷)和全新题目组成。刷题时可以参考以下策略:
-
关注历年真题:
- 题库中的旧题占比较大,建议优先刷历年的A卷、B卷、C卷、D卷题目。
- 对于每道题目,建议深度理解其解题思路、代码实现,以及相关算法的适用场景。
-
适应新题目:
- E卷中包含全新题目,需要掌握全面的算法知识和一定的灵活应对能力。
- 建议关注新的刷题平台或交流群,获取最新题目的解析和动态。
-
掌握常见算法:
华为OD考试通常涉及以下算法和数据结构:- 排序算法(快速排序、归并排序等)
- 动态规划(背包问题、最长公共子序列等)
- 贪心算法
- 栈、队列、链表的操作
- 图论(最短路径、最小生成树等)
- 滑动窗口、双指针算法
-
保持编程规范:
- 注重代码的可读性和注释的清晰度。
- 熟练使用常见编程语言,如C++、Java、Python等。
如何获取资源?
-
官方参考:
- 华为招聘官网或相关的招聘平台会有一些参考信息。
- 华为OD的相关公众号可能也会发布相关的刷题资料或学习资源。
-
加入刷题社区:
- 找到可信的刷题交流群,与其他备考的小伙伴交流经验。
- 关注知名的刷题网站,如LeetCode、牛客网等,这些平台上有许多华为OD的历年真题和解析。
-
寻找系统性的教程:
- 学习一本经典的算法书籍,例如《算法导论》《剑指Offer》《编程之美》等。
- 完成系统的学习课程,例如数据结构与算法的在线课程。
积极心态与持续努力:
刷题的过程可能会比较枯燥,但它能够显著提升编程能力和算法思维。无论是为了通过华为OD的招聘考试,还是为了未来的职业发展,这些积累都会成为重要的财富。
考试注意细节
-
本地编写代码
- 在本地 IDE(如 VS Code、PyCharm 等)上编写、保存和调试代码,确保逻辑正确后再复制粘贴到考试页面。这样可以减少语法错误,提高代码准确性。
-
调整心态,保持冷静
- 遇到提示不足或实现不确定的问题时,不必慌张,可以采用更简单或更有把握的方法替代,确保思路清晰。
-
输入输出完整性
- 注意训练和考试时都需要编写完整的输入输出代码,尤其是和题目示例保持一致。完成代码后务必及时调试,确保功能符合要求。
-
快捷键使用
- 删除行可用
Ctrl+D
,复制、粘贴和撤销分别为Ctrl+C
,Ctrl+V
,Ctrl+Z
,这些可以正常使用。 - 避免使用
Ctrl+S
,以免触发浏览器的保存功能。
- 删除行可用
-
浏览器要求
- 使用最新版的 Google Chrome 浏览器完成考试,确保摄像头开启并正常工作。考试期间不要切换到其他网站,以免影响考试成绩。
-
交卷相关
- 答题前,务必仔细查看题目示例,避免遗漏要求。
- 每完成一道题后,点击【保存并调试】按钮,多次保存和调试是允许的,系统会记录得分最高的一次结果。完成所有题目后,点击【提交本题型】按钮。
- 确保在考试结束前提交试卷,避免因未保存或调试失误而丢分。
-
时间和分数安排
- 总时间:150 分钟;总分:400 分。
- 试卷结构:2 道一星难度题(每题 100 分),1 道二星难度题(200 分)。及格分为 150 分。合理分配时间,优先完成自己擅长的题目。
-
考试环境准备
- 考试前请备好草稿纸和笔。考试中尽量避免离开座位,确保监控画面正常。
- 如需上厕所,请提前规划好时间以减少中途离开监控的可能性。
-
技术问题处理
- 如果考试中遇到断电、断网、死机等技术问题,可以关闭浏览器并重新打开试卷链接继续作答。
- 出现其他问题,请第一时间联系 HR 或监考人员进行反馈。
祝你考试顺利,取得理想成绩!
相关文章:

【2024年华为OD机试】 (C卷,200分)- 贪心歌手(JavaScriptJava PythonC/C++)
一、问题描述 问题描述 一个歌手需要从A城前往B城参加演出,必须在T天内到达。途中会经过N座城市,且不能往回走。每两座城市之间的行程天数已知。歌手在每座城市都可以卖唱赚钱,但收入会随着停留天数的增加而递减。具体来说,第一…...

深度学习在金融风控中的应用:突破传统模型的瓶颈
深度学习在金融风控中的应用:突破传统模型的瓶颈 金融风险控制(简称“风控”)是现代金融体系中至关重要的一环,关系到金融机构的稳定性、客户的安全以及整体经济的健康运行。近年来,随着深度学习的迅猛发展,传统的风控模型正面临被颠覆的挑战,新的技术手段和思维方式正…...

LLM - 大模型 ScallingLaws 的指导模型设计与实验环境(PLM) 教程(4)
欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://spike.blog.csdn.net/article/details/145323420 免责声明:本文来源于个人知识与公开资料,仅用于学术交流,欢迎讨论,不支持转载。 Scaling Laws (缩放法则) 是大模型领域中,用于描述 模型性能(Loss) 与…...

hunyuan 混元学习
使用了5个subset,也是用了text-image和text-video进行训练的 也是进行了复杂的视频选择。同movie gen. 也进行了模型切断,用拉普拉斯算子找到最清晰的一帧作为训练的起始 训练了不同的模型去选择数据,比如用Dover去选择美观度比较好的数据,…...

开发、科研工具汇总
一些基础教程网站 W3:w3school 在线教程 菜鸟:菜鸟教程 - 学的不仅是技术,更是梦想! 开发相关参考文档 Vue2:Vue.js Vue3:Vue.js - 渐进式 JavaScript 框架 | Vue.js MDN:MDN Web Docs HT…...

项目部署(springboot项目)
1、安装Nginx,并开启 2、前端项目打包:npm run build:prod--->dist 3、后端项目打包:install--->xxx.jar 4、开放需要的端口号:比如我的后端项目端口号为8282,则需要防火墙和服务器同时开发8282端口 5、将di…...

OpenEuler学习笔记(十四):在OpenEuler上搭建.NET运行环境
一、在OpenEuler上搭建.NET运行环境 基于包管理器安装 添加Microsoft软件源:运行命令sudo rpm -Uvh https://packages.microsoft.com/config/centos/8/packages-microsoft-prod.rpm,将Microsoft软件源添加到系统中,以便后续能够从该源安装.…...

神经网络的通俗介绍
人工神经网络,是一种模仿人类大脑工作原理的数学模型。人类的大脑是由无数的小“工作站”组成的,每个工作站叫做“神经元”。这些神经元通过“电线”互相连接,负责接收、处理和传递信息。 一、人类大脑神经网络 人类大脑的神经网络大概长这…...

基于 AWS SageMaker 对 DeepSeek-R1-Distilled-Llama-8B 模型的精调与实践
在当今人工智能蓬勃发展的时代,语言模型的性能优化和定制化成为研究与应用的关键方向。本文聚焦于 AWS SageMaker 平台上对 DeepSeek-R1-Distilled-Llama-8B 模型的精调实践,详细探讨这一过程中的技术细节、操作步骤以及实践价值。 一、实验背景与目标 …...

如何使用DeepSeek R1
以下是如何使用DeepSeek R1的详细步骤: ### 一、注册DeepSeek账户 1. **访问官方网站**: - 打开浏览器,访问[chat.deepseek.com](http://chat.deepseek.com)。 2. **注册账户**: - 使用电子邮件、Google账户或86手机号码…...

大屏 UI 设计风格的未来趋势
在科技飞速革新的时代,大屏设备的应用领域不断拓展,从城市的智能交通指挥中心,到商场的互动广告大屏,再到家庭的超大尺寸智能电视,大屏已然成为信息展示与交互的关键载体。大屏 UI 设计风格也随之不断演变,…...

unity学习22:Application类其他功能
目录 1 是否允许后台运行 1.1 Application.runInBackground,显示是否允许后台运行 1.2 设置的地方 2 打开URL 2.1 Application.OpenURL("") 打开超链接 3 退出游戏 3.1 Application.Quit() 退出游戏 4 场景相关 5 返回游戏状态 6 控制游戏的行…...

51单片机入门_02_C语言基础0102
C语言基础部分可以参考我之前写的专栏C语言基础入门48篇 以及《从入门到就业C全栈班》中的C语言部分,本篇将会结合51单片机讲差异部分。 课程主要按照以下目录进行介绍。 文章目录 1. 进制转换2. C语言简介3. C语言中基本数据类型4. 标识符与关键字5. 变量与常量6.…...

定位的叠放次序 z-index
浮动定位和绝对定位的区别: 浮动只会压住它下面标准流的盒子,但是不会压住下面标准流盒子里面的文字,但是绝对定位(固定定位)会压住下面标准流所有的内容。...

ESP32-S3模组上跑通esp32-camera(36)
接前一篇文章:ESP32-S3模组上跑通esp32-camera(35) 一、OV5640初始化 2. 相机初始化及图像传感器配置 上一回继续对reset函数的后一段代码进行解析。为了便于理解和回顾,再次贴出reset函数源码,在components\esp32-camera\sensors\ov5640.c中,如下: static int reset…...

前端性能优化:HMR热更新和预获取加载
最近发现项目开发,有点加载快,有点却是卡机式,甚至刷新导致白屏情况。于是,我找开发和性能优化的方法,找到下面几种。 本文将深入探讨 预获取(Prefetch)、动态导入(Dynamic Import&…...

【自学笔记】计算机网络的重点知识点-持续更新
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 计算机网络重点知识点一、计算机网络概述二、网络分类三、网络性能指标四、网络协议与体系结构五、数据交换方式六、物理层与数据链路层七、网络层与运输层八、应用…...

算法基础学习——二分查找(附带Java模板)
有单调性的数列一定可以使用二分,没有单调性的题目也可能可以使用二分; (一)整数二分 二分的本质: 在某个整数区间内,存在某种性质使得区间内左半边的数都不满足该性质;而右半边的数都满足该性…...

【llm对话系统】大模型源码分析之llama模型的long context更长上下文支持
1. 引言 Llama模型的一个重要特性是支持长上下文处理。本文将深入分析Llama源码中实现长上下文的关键技术点,包括位置编码(position embedding)的外推方法、注意力机制的优化等。我们将通过详细的代码解析来理解其实现原理。 2. 位置编码的外推实现 2.1 旋转位置…...

单片机基础模块学习——NE555芯片
一、NE555电路图 NE555也称555定时器,本文主要利用NE555产生方波发生电路。整个电路相当于频率可调的方波发生器。 通过调整电位器的阻值,方波的频率也随之改变。 RB3在开发板的位置如下图 测量方波信号的引脚为SIGHAL,由上面的电路图可知,NE555已经构成完整的方波发生电…...

Hive:struct数据类型,内置函数(日期,字符串,类型转换,数学)
struct STRUCT(结构体)是一种复合数据类型,它允许你将多个字段组合成一个单一的值, 常用于处理嵌套数据,例如当你需要在一个表中存储有关另一个实体的信息时。你可以使用 STRUCT 函数来创建一个结构体。STRUCT 函数接受多个参数&…...

最优化问题 - 内点法
以下是一种循序推理的方式,来帮助你从基础概念出发,理解 内点法(Interior-Point Method, IPM) 是什么、为什么要用它,以及它是如何工作的。 1. 问题起点:带不等式约束的优化 假设你有一个带不等式约束的优…...

vim交换文件的工作原理
在vim中,交换文件是一个临时文件,当我们使用vim打开一个文件进行编辑(一定得是做出了修改才会产生交换文件)时候,vim就会自动创建一个交换文件,而之后我们对于文件的一系列修改都是在交换文件中进行的&…...

CISCO路由基础全集
第一章:交换机的工作原理和基本技能_交换机有操作系统吗-CSDN博客文章浏览阅读1.1k次,点赞24次,收藏24次。交换机可看成是一台特殊的计算机,同样有CPU、存储介质和操作系统,只是与计算机的稍有不同。作为数据交换设备&…...

网络直播时代的营销新策略:基于受众分析与开源AI智能名片2+1链动模式S2B2C商城小程序源码的探索
摘要:随着互联网技术的飞速发展,网络直播作为一种新兴的、极具影响力的媒体形式,正逐渐改变着人们的娱乐方式、消费习惯乃至社交模式。据中国互联网络信息中心数据显示,网络直播用户规模已达到3.25亿,占网民总数的45.8…...

2024年终总结——今年是蜕变的一年
2024年终总结 摘要前因转折找工作工作的成长人生的意义 摘要 2024我从国企出来,兜兜转转还是去了北京,一边是工资低、感情受挫,一边是压力大、项目经历少,让我一度找不到自己梦寐以求的工作,我投了一家又一家ÿ…...

AutoDL 云服务器:普通 用户 miniconda 配置
AutoDL 初始状态下只有root用户,miniconda 安装在root用户目录下 /// 增加普通用户 rootautodl-container-1c0641804d-5bb7040c:~/Desktop# apt updaterootautodl-container-1c0641804d-5bb7040c:~/Desktop# apt install sudorootautodl-container-1c0641804d-5…...

渲染流程概述
渲染流程包括 CPU应用程序端渲染逻辑 和 GPU渲染管线 一、CPU应用程序端渲染逻辑 剔除操作对物体进行渲染排序打包数据调用Shader SetPassCall 和 Drawcall 1.剔除操作 视椎体剔除 (给物体一个包围盒,利用包围盒和摄像机的视椎体进行碰撞检测…...

前端力扣刷题 | 4:hot100之 子串
560. 和为K的子数组 给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 。 子数组是数组中元素的连续非空序列。 示例: 输入:nums [1,1,1], k 2 输出:2 法一:暴力法 var subar…...

Julia 之 @btime 精准测量详解
Julia 语言因其高性能和易用性在科学计算、数据分析等领域获得了广泛关注。在性能优化中,精准测量代码执行时间是至关重要的任务,而 Julia 提供了强大的工具 btime 来辅助这一任务。本文将围绕 Julia 的 btime 来展开,帮助读者深入理解并高效…...