题目描述
算法工程师小明面对着这样一个问题 ,需要将通信用的信道分配给尽量多的用户:
信道的条件及分配规则如下:
所有信道都有属性:”阶”。阶为 r的信道的容量为 2^r比特;
所有用户需要传输的数据量都一样:D比特;
一个用户可以分配多个信道,但每个信道只能分配给一个用户;
只有当分配给一个用户的所有信道的容量和>=D,用户才能传输数据;
给出一组信道资源,最多可以为多少用户传输数据?
输入描述
第一行,一个数字 R。R为最大阶数。
0<=R<20
第二行,R+1个数字,用空格隔开。代表每种信道的数量 Ni。按照阶的值从小到大排列。
0<=i<=R,0<=Ni<1000.
第三行,一个数字 D。D为单个用户需要传输的数据量。
0<D<1000000
输出描述
一个数字(代表最多可以供多少用户传输数据)
用例
输入 | 5 10 5 0 1 3 2 30 |
输出 | 4 |
说明 | 无 |
信道分配问题:贪心算法的应用
核心解题思路
问题分析
题目要求将不同阶的信道分配给用户,使得满足条件的用户数量最大化。关键点包括:
- 信道特性:阶为r的信道容量为2^r比特
- 用户需求:每个用户需要总容量≥D比特
- 分配规则:一个用户可占用多个信道,但一个信道只能给一个用户
解决方案:贪心算法
- 信道排序:按容量从小到大排序(阶从小到大)
- 贪心分配:
- 尽可能用小信道满足用户需求
- 当小信道不足时,用大信道补充
- 组合优化:计算每种阶的信道能贡献多少用户
完整代码实现
def max_users(R, channels, D):
"""
计算最多可以满足多少用户
参数:
R: 最大阶数
channels: 各阶信道的数量列表
D: 单个用户需求容量
返回:
最多可满足的用户数
"""
# 计算各阶信道的容量
capacities = [2**r for r in range(R+1)]
# 总容量检查
total_capacity = sum(c * cap for c, cap in zip(channels, capacities))
if total_capacity < D:
return 0
# 从低阶到高阶处理信道
users = 0
remaining = D
# 我们需要将信道按阶从小到大处理
for r in range(R+1):
cap = capacities[r]
count = channels[r]
# 当前阶信道能贡献多少用户
max_possible = remaining // cap
if max_possible == 0:
# 需要更大的信道
remaining %= cap
continue
# 实际能使用的信道数
use = min(count, max_possible)
users += use
remaining -= use * cap
if remaining == 0:
# 当前用户需求已满足,准备下一个用户
remaining = D
# 处理剩余的大信道
for r in range(R, -1, -1):
cap = capacities[r]
count = channels[r]
if count == 0:
continue
# 每个大信道可以满足一个用户
users += count
return users
# 主程序
if __name__ == "__main__":
import sys
input_lines = sys.stdin.read().splitlines()
R = int(input_lines[0])
channels = list(map(int, input_lines[1].split()))
D = int(input_lines[2])
# 检查输入有效性
if len(channels) != R + 1:
print(0)
else:
result = max_users(R, channels, D)
print(result)
示例解析
示例1:输入"5",“10 5 0 1 3 2”,“30”
- 信道容量计算:
- 阶0: 1 (数量10)
- 阶1: 2 (数量5)
- 阶2: 4 (数量0)
- 阶3: 8 (数量1)
- 阶4: 16 (数量3)
- 阶5: 32 (数量2)
- 贪心分配过程:
- 用户1: 16+8+4+2=30 (使用阶3,4,1的信道)
- 用户2: 16+8+4+2=30 (同上)
- 用户3: 32 (阶5)
- 用户4: 32 (阶5)
- 结果:4个用户
示例2:输入"3",“5 3 2 1”,“10”
- 信道容量:
- 阶0: 1 (5)
- 阶1: 2 (3)
- 阶2: 4 (2)
- 阶3: 8 (1)
- 分配过程:
- 用户1: 8+2=10 (阶3+1)
- 用户2: 4+4+2=10 (阶2+2+1)
- 用户3: 4+2+2+1+1=10 (阶2+1+1+0+0)
- 结果:3个用户
示例3:输入"2",“1 1 1”,“5”
- 信道容量:
- 阶0: 1 (1)
- 阶1: 2 (1)
- 阶2: 4 (1)
- 分配过程:
- 用户1: 4+1=5 (阶2+0)
- 结果:1个用户
总结
算法特点
- 高效性:时间复杂度O®,R为最大阶数
- 正确性:保证最大化用户数量
- 简洁性:逻辑清晰,易于实现
- 实用性:适用于资源分配类问题
关键要点
- 容量计算:
2^r
快速计算信道容量 - 贪心策略:
- 优先使用小容量信道
- 不足时用大容量信道补充
- 边界处理:
- 检查总容量是否足够
- 处理剩余大信道
应用场景
- 通信资源分配
- 云计算资源调度
- 任务分配优化
- 带宽分配问题
- 存储空间分配
该解法通过贪心算法有效解决了信道资源分配问题,在保证最大化用户数量的同时具有较高的效率。算法实现简洁明了,适用于各种规模的输入数据,是处理此类资源分配问题的经典方法。