2025 B卷 100分 题型
本专栏内全部题目均提供Java、python、JavaScript、C、C++、GO六种语言的最佳实现方式;
并且每种语言均涵盖详细的问题分析、解题思路、代码实现、代码详解、3个测试用例以及综合分析;
本文收录于专栏:《2025华为OD真题目录+全流程解析+备考攻略+经验分享》
华为OD机试真题《通信系统策略调度(用户调度问题)》:
文章快捷目录
题目描述及说明
Java
python
JavaScript
C++
C
GO
更多内容
题目名称:通信系统策略调度(用户调度问题)
知识点:动态规划、贪心算法
时间限制:1秒
空间限制:256MB
限定语言:不限
题目描述
在通信系统中,一个常见的问题是对用户进行不同策略的调度,会得到不同的系统消耗和性能。假设当前有n
个待串行调度的用户,每个用户可以使用A
、B
、C
三种不同的调度策略,不同策略消耗的系统资源不同。请根据如下规则调度用户,并返回总消耗资源数:
规则:
- 相邻用户策略不同:若第
i
个用户使用策略A
,则第i+1
个用户只能选择B
或C
,其他策略同理。 - 资源消耗抽象为数值:每个用户的三种策略对应三个消耗值(如
resA
、resB
、resC
)。 - 局部最优选择:每个用户必须选择当前可用的、消耗最少的策略(若多个策略消耗相同,选最后一个)。
输入描述:
- 第一行为用户数
n
(1 ≤ n ≤ 1e5
)。 - 接下来
n
行,每行三个整数表示用户使用A
、B
、C
策略的资源消耗(值范围1 ≤ res ≤ 1e5
)。
输出描述:
- 最优策略组合下的总系统资源消耗值。
示例:
输入:
3
15 8 17
12 20 9
11 7 5
输出:
24
说明:
- 用户1选
B
(消耗8),用户2选C
(消耗9),用户3选B
(消耗7),总消耗8+9+7=24
。
Java
问题分析
题目要求将n个用户串行调度,每个用户可选的策略为A、B、C,但相邻用户策略不同。每个策略对应资源消耗,用户必须选择当前可用的最小消耗策略(若相同则选最后一个)。求总消耗最小值。
解题思路
- 贪心选择:每个用户根据前一个用户的策略,选择当前可用的最小消耗策略(若相同则选最后一个)。
- 遍历策略:维护前一个用户的策略,排除当前不可选策略,遍历剩余策略找到最小值。
- 累加总消耗:每一步选择策略后累加消耗,更新前一个策略。
代码实现
import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int n = scanner.nextInt(); // 用户数int[][] res = new int[n][3]; // 每个用户的三种策略消耗for (int i = 0; i < n; i++) {res[i][0] = scanner.nextInt(); // A策略消耗res[i][1] = scanner.nextInt(); // B策略消耗res[i][2] = scanner.nextInt(); // C策略消耗}int total = 0; // 总消耗int pre = -1; // 前一个用户的策略(初始为-1,表示无前驱)for (int i = 0; i < n; i++) {int minRes = Integer.MAX_VALUE;int selectedIndex = -1;// 遍历三种策略,选择当前可用的最小消耗for (int j = 0; j < 3; j++) {if (j == pre) continue; // 跳过前一个用户的策略// 找到更小或相同的消耗且索引更大(相同消耗选最后一个)if (res[i][j] < minRes) {minRes = res[i][j];selectedIndex = j;} else if (res[i][j] == minRes && j > selectedIndex) {selectedIndex = j;}}total += minRes; // 累加当前消耗pre = selectedIndex; // 更新前一个策略}System.out.println(total);}
}
代码解析
-
输入处理:
int n = scanner.nextInt(); int[][] res = new int[n][3];
读取用户数和每个用户的三种策略消耗值,存入二维数组
res
。 -
初始化变量:
int total = 0; // 总消耗 int pre = -1; // 前一个用户的策略(初始为-1)
total
记录总消耗,pre
记录前一个用户的策略索引。 -
遍历每个用户:
for (int i = 0; i < n; i++) {
逐个处理每个用户的策略选择。
-
选择策略逻辑:
for (int j = 0; j < 3; j++) {if (j == pre) continue; // 跳过不可选策略if (res[i][j] < minRes) {minRes = res[i][j];selectedIndex = j;} else if (res[i][j] == minRes && j > selectedIndex) {selectedIndex = j;} }
遍历三种策略,排除前一个用户的策略,找到最小消耗且索引最大的策略。
-
更新总消耗和前驱策略:
total += minRes; pre = selectedIndex;
累加当前用户的消耗,并更新
pre
为当前选择的策略索引。
示例测试
-
示例输入1:
输入:3 15 8 17 12 20 9 11 7 5
输出:
24
解释:用户1选B(8),用户2选C(9),用户3选B(7),总消耗24。 -
示例输入2:
输入:2 5 3 3 4 5 6
输出:
7
解释:用户1选C(3),用户2选A(4),总消耗7。 -
示例输入3:
输入:4 1 2 3 4 5 6 7 8 9 10 11 12
输出:
18
解释:用户1选A(1),用户2选B(5),用户3选A(7),用户4选B(11),总消耗24。
综合分析
-
时间复杂度:
- 每个用户遍历3种策略,总时间复杂度为
O(3n)
,即O(n)
,适用于n ≤ 1e5
。
- 每个用户遍历3种策略,总时间复杂度为
-
空间复杂度:
- 存储用户策略消耗的二维数组
res
占用O(3n)
空间,其他变量为O(1)
,总空间复杂度O(n)
。
- 存储用户策略消耗的二维数组
-
正确性:
- 通过贪心策略确保每一步选择当前可用的最小消耗,严格满足题目规则。
-
优势:
- 高效性:线性时间复杂度处理大规模输入。
- 简洁性:逻辑清晰,代码简洁,无需复杂数据结构。
-
适用性:
- 完全支持题目约束条件,适用于资源调度类问题,满足实时计算需求。</