华为OD机试B卷机房布局解析(Python解题指南及详细思路)
题目描述
小明正在规划一个大型数据中心机房,为了使得机柜上的机器都能正常满负荷工作,需要确保在每个机柜边上至少要有一个电箱。
为了简化题目,假设这个机房是一整排,M表示机柜,I表示间隔,请你返回这整排机柜,至少需要多少个电箱。 如果无解请返回 -1 。
输入描述
cabinets = “MIIM”
其中 M 表示机柜,I 表示间隔
输出描述
2
表示至少需要2个电箱
备注 1 ≤ strlen(cabinets) ≤ 10000 其中 cabinets[i] = ‘M’ 或者 ‘I’
用例
| 输入 | MIIM |
| 输出 | 2 |
| 说明 | 无 |
| 输入 | MIM |
| 输出 | 1 |
| 说明 | 无 |
| 输入 | M |
| 输出 | -1 |
| 说明 | 无 |
| 输入 | MMM |
| 输出 | -1 |
| 说明 | 无 |
| 输入 | I |
| 输出 | 0 |
| 说明 | 无 |
数据中心机房电箱规划问题:简单贪心解法
核心解题思路
作为初学者,我们可能第一反应是暴力枚举所有可能放電箱的位置,但那样时间复杂度太高(O(2^n)),不适合长字符串。贪心算法是更好的选择:从左到右扫描字符串,每次遇到一个机柜('M')时,优先尝试用右边的间隔('I')来覆盖它,如果不行再用左边,否则就判定无解。
为什么贪心有效?
'I' 上,可以覆盖左边和/或右边的 'M'。但每个 'M' 只需要被覆盖一次。'M' 都被及时覆盖。优先用右边 'I' 覆盖,可以共享给后续 'M',从而最小化电箱数(例如 "MIM" 只需要一个电箱)。'M' 左边和右边都没有 'I',或者连续多个 'M' 没有间隔,则无解(如 "M" 或 "MMM")。算法步骤:
- 初始化:计数器
count记录电箱数,数组placed记录每个位置是否已放电箱(避免重复放置)。 - 扫描字符串:对每个字符:
- 如果是
'I',跳过(我们只在遇到'M'时行动)。 - 如果是
'M': - 检查是否已被覆盖(左边或右边已有电箱)。
- 如果未被覆盖:
- 优先尝试在右边放電箱(如果右边是
'I')。 - 如果右边不行,尝试在左边放電箱(如果左边是
'I')。 - 如果都不行,返回
-1。 - 返回结果:
count就是最少电箱数。
这个算法时间复杂度 O(n),只扫描一次字符串,非常高效。
代码实现
# 输入部分:读取字符串
cabinets = input().strip()
# 主体函数:计算最少电箱数
def min_electric_boxes(cabinets):
n = len(cabinets)
# 如果没有机柜,返回0
if 'M' not in cabinets:
return 0
# 初始化:count记录电箱数,placed记录位置是否已放电箱
count = 0
placed = [False] * n # placed[i]为True表示在i位置放电箱
# 遍历每个字符
for i in range(n):
if cabinets[i] == 'M': # 遇到机柜
covered = False
# 检查是否已被覆盖:左边或右边已有电箱
if i - 1 >= 0 and cabinets[i-1] == 'I' and placed[i-1]:
covered = True # 左边有电箱覆盖
if not covered and i + 1 < n and cabinets[i+1] == 'I' and placed[i+1]:
covered = True # 右边有电箱覆盖
if not covered: # 如果未被覆盖,尝试覆盖
# 优先用右边间隔放电箱
if i + 1 < n and cabinets[i+1] == 'I':
placed[i+1] = True # 放电箱
count += 1
# 右边不行,用左边间隔放电箱
elif i - 1 >= 0 and cabinets[i-1] == 'I':
placed[i-1] = True # 放电箱
count += 1
else: # 左右都不行,无解
return -1
return count
# 输出部分:调用函数并打印
result = min_electric_boxes(cabinets)
print(result)
代码详解
cabinets = input().strip() 直接读取输入字符串,简单高效。'M',如果没有,直接返回 0(如输入 "I")。placed 列表跟踪电箱位置,避免重复放置。'M':
-1。示例测试
用题目例子验证:
"MIIM":遍历时:
'M'),未被覆盖,放右边 (i=1) 电箱,count=1。'M'),未被覆盖,放左边 (i=2) 电箱,count=2。输出 2。"MIM":
'M'),放右边 (i=1) 电箱,count=1。'M'),左边 (i=1) 已有电箱,覆盖。输出 1。"M":i=0 ('M'),左右无 'I',返回 -1。"MMM":i=0 ('M'),右边是 'M' 不是 'I',且左边无,返回 -1。"I":无 'M',返回 0。总结
这道题教会我们,贪心算法在覆盖类问题中非常实用:从左到右扫描,及时覆盖每个机柜,优先共享电箱。关键点:
作为初学者,多从简单例子入手,理解贪心策略的“局部最优导致全局最优”思想。希望这篇博客帮你掌握这道题!如果有疑问,欢迎留言讨论。
作者:蜗牛的旷野