华为OD机试统一考试D卷C卷 - 信道分配

信道分配

题目描述

算法工程师小明面对着这样一个问题。需要将通信用的信道分配给尽量多的用户,信道的条件及分配规则如下

1.所有信道都有属性:”阶”。阶为r的信道的容量为2^r比特

2.所有用户需要传输的数据量都一样:D比特

3.一个用户可以分配多个信道,但每个信道只能分配给一个用户

4.只有当分配给一个用户的所有信道的容量和>=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

3

6 2 5 7

13

输出6

解题思路:

1,这个题难度中等吧,最开始我想到的是动态规划,应该是可以的,类似于力扣上的找硬币,找硬币每个币数量是无限的,这儿是有数目限制,但这不是障碍。

2,第二个解法就是知乎有一篇将数字D转为2进制类似于100101,然后和阶数R进行加减换算,这个思路很奇特很天才,刚好利用到阶,华为od机试 信道分配 - 知乎,如果理解了就很简单,没理解就懵逼。

3,我这边最终是用贪心递归解,实现代码没保存,代码量并不多,思路也简单

a,先用Map保存每个信道阶的数量映射关系,比如 32->2 16->3 8->1 4->0 2->5 1->10

b,然后启动递归从大到小遍历,递归分递推和回溯,首先在递推的过程中遵守一个原则,如果能满足,则尽量多消耗这个数,不满足则去下一个低阶,比如D=30,遇到R32的时候,32此时太大,用掉可能会浪费,先不使用看下一个更小的适不适合,遇到R=16,用掉1个不够,用掉2个又超了会浪费,那就先用1个,此时R=16的数量映射就变为R16->2,D=14。遇到R8的时候可以使用1个,此时 R8->0,D=6, 遇到R4数量为0跳过,到R2,最多使用3个刚好满足D=0,此时R2->2。已经满足结束递推,返回D值,进入回溯阶段(大多数情况要到R1才是递推结束条件)。

c,进入到回溯,从低阶到高阶,比如R1回到R2,最终到R32,每一层都判断返回的D是否为0,D=0说明已经分配成功,不处理直接抛给更高阶,D>0说明前面还没匹配成功,则看自己还有剩余,尽量将这个D变为0(比如回到R8,此时D=5,还差5个,刚好R8还剩一个,那将8分配给5,然后上抛0给上层R16,这个过程多少都会开始浪费),若自己也不够继续上抛,直到最高阶R32的时候,如果能将D干为0则成功分配+1,否则说明所有阶的数量都凑不够一个D,递归结束。

代码量其实不多,主要理解一个思路,在向低阶递推的时候在不浪费的情况下,先尽量多的使用自己,在向高阶回朔的时候将浪费尽量留给低阶,这样浪费的就最少(最开始我这边一直纠结到底是先消耗低阶的还是高阶)

最终就得到最适合的答案

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值