华为OD机考双机位C卷 - 乘坐保密电梯 (Java & Python & JS & GO & C++ & C)
乘坐保密电梯
2026华为OD机试双机位C卷 - 华为OD上机考试双机位C卷
华为OD机试双机位C卷真题目录点击查看: 【全网首发】2026华为OD机位C卷 机考真题题库含考点说明以及在线OJ(OD上机考试双机位C卷)
题目描述
有一座保密大楼,你从0楼到达指定楼层m,必须这样的规则乘坐电梯:
给定一个数字序列,每次根据序列中的数字n,上升n层或者下降n层,前后两次的方向必须相反,规定首次的方向向上,自行组织序列的顺序按规定操作到达指定楼层。
求解到达楼层的序列组合,如果不能到达楼层,给出小于该楼层的最近序列组合。
输入描述
第一行:期望的楼层,取值范围[1,50]; 序列总个数,取值范围[1,23]
第二行:序列,每个值取值范围[1,50]
备注
-
操作电梯时不限定楼层范围。
-
必须对序列中的每个项进行操作,不能只使用一部分。
输出描述
能够达到楼层或者小于该楼层最近的序列
示例1
输入
5 3
1 2 6
输出
6 2 1
说明
1 2 6,6 2 1均为可行解,按先处理大值的原则结果为6 2 1
解题思路
1. 问题转化
电梯的运动规则是“上升、下降、上升、下降……”,这实际上是将给定的数字序列分成了两个集合:
- 上升集合 (Up Set, 记为 $U$):用于第 1、3、5... 次操作,对楼层做加法。
- 下降集合 (Down Set, 记为 $D$):用于第 2、4、6... 次操作,对楼层做减法。
设所有数字的总和为 $S$,则最终到达的楼层 $H$ 可以表示为:
$$ H = \sum U - \sum D $$
代入 $\sum D = S - \sum U$,得到:
$$ H = 2 \sum U - S $$
题目要求 $H \le m$ 且尽可能接近 $m$(即 $H$ 最大),这等价于要求 $\sum U$ 满足:
$$ 2 \sum U - S \le m \implies \sum U \le \frac{S + m}{2} $$
因此,问题转化为:从给定数组中选出一个子集 $U$,使其元素之和尽可能大,但不超过 $\lfloor \frac{S + m}{2} \rfloor$。
2. 约束条件确定
- 子集大小固定:由于序列必须用完且交替操作,集合 $U$ 的元素个数必须是固定的。
- 如果总个数 $n$ 是偶数,则 $|U| = n/2$。
- 如果总个数 $n$ 是奇数,则 $|U| = (n+1)/2$(因为第一次必须上升)。
- 目标:找到满足上述大小要求,且和最大的子集 $U$。
3. 算法选择:深度优先搜索 (DFS)
由于 $n$ 的范围较小($[1, 23]$),可以使用 DFS(回溯法)来搜索所有可能的子集 $U$。
- 排序优化:先将数组降序排序。在 DFS 过程中,优先尝试选择较大的数,这样可以更快地逼近最大限制和,结合剪枝策略可以显著提高效率。
- 剪枝策略:
- 如果当前选的个数超过了规定的大小,停止。
- 如果当前和已经超过了限制值 $\lfloor \frac{S + m}{2} \rfloor$,停止。
- (进阶)如果当前和加上剩余所有数都不足以超过已知的最优解,停止。
4. 结果构造与字典序优化
当找到一个满足条件的最佳子集 $U$ 后(剩余元素即为集合 $D$),需要构造最终的输出序列。
题目要求“序列组合”且示例暗示了字典序最大(6 2 1 优于 1 2 6)。
- 贪心策略:为了让序列的字典序最大,我们应该在每一步都尽可能选择当前可用的最大值。
- 具体操作:
- 将集合 $U$ 降序排序。
- 将集合 $D$ 降序排序。
- 交替从 $U$ 和 $D$ 中取出最大的元素放入结果序列(顺序为:$U_1, D_1, U_2, D_2, \dots$)。
浙公网安备 33010602011771号