信道分配
题目描述
算法工程师小明面对着这样一个问题。需要将通信用的信道分配给尽量多的用户,信道的条件及分配规则如下
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,递归结束。
代码量其实不多,主要理解一个思路,在向低阶递推的时候在不浪费的情况下,先尽量多的使用自己,在向高阶回朔的时候将浪费尽量留给低阶,这样浪费的就最少(最开始我这边一直纠结到底是先消耗低阶的还是高阶)
最终就得到最适合的答案