队名:来点儿朗姆酒
成绩:杭厦赛区,复赛练习赛第五,复赛正式赛第七。后复活赛复活成功,进入决赛。
心得:自本科毕业之后,就没有机会参加质量很高的竞赛了,怀念ACM的感觉。这次软挑全力以赴做了快一个月,最后一周甚至有点废寝忘食了,除了数模通过宵,这已经是我在杭电回寝最晚的记录了。非常感谢我的队友,朝夕相处,分担压力的同时互相鼓励,心态是真的好,虽然三个人轮流叫嚣着摆烂,但没有放弃,最后几天冲进了前四,仿佛看到了光。但是现场复赛的时候,因为判题器出了些问题,优化无效,最后没能进决赛,很遗憾。不过在一众老哥的坚持下,华为增加了复活赛,最终复活成功,进入了决赛,但是当时已经决定考公,没有心情研究赛题了,就没有做决赛的题,以下的思路是针对复赛的。
题目:本赛题以华为云视频直播服务流量调度问题为基础,并进行一定的抽象、调整和简化。参赛选手需要设计高效的调度算法,在满足客户要求 的前提下,通过对流量的合理调度,最小化网络使用成本。
题目补充:T个时刻,N个用户节点,M个边缘节点。已知用户需求、边缘节点总容量,和每个用户&每个边缘节点的qos(用来判断可否连接)。
每个用户n在时刻t会有L种流,流的大小是需求大小,流不可拆分。
需要将所有流放入边缘节点,计算每个边缘节点的成本,累计所有边缘节点的成本即为成绩。
边缘节点的成本计算方式:将每个时刻的成本从大到小排序,取95%号位的成本为该节点的成本。
即成本序列为 100,99,95,94... 取T*5%位置的值为成本。
复赛现场变更点:任意选取 10 个边缘节点。这些边缘节点的计费规则由原来的 95 百分位计费改为 90 百分位计费。
思路:成本计算规则是95%号位,很容易想到前5%的成本是可以“白嫖”的,将节点的前5%和95%分开讨论可以得到较优的解。
对于前5%:选取节点进行“白嫖”操作,使其前5%的成本尽量大,可以处理掉更多的需求。
这里有几种方案供参考:
1.以节点为最外层循环,根据不同的排序规则(如容量大的、qos连接更多用户的等,也可以根据多因素调参)对节点进行排序。每取一个节点,让其处理完T*5%的时间后再取下一个节点继续做。 -- 最优解
2.以节点为最外层循环,把节点按照“可以处理流的大小”排序。但是每次取出来的节点,只做1个时刻,处理完之后节点“可以处理流的大小”更新,再取下一个节点。这个要标记“同一个节点在一个时刻只能白嫖一次”。
3.以时间为最外层循环。根据不同的排序规则(如总流量最大的等)对时间进行排序。确定时刻之后,选择一个节点(选择方法可以参考1)对其进行白嫖。
4.以时间为最外层循环。虽然是白嫖,但是考虑“均分”的思想,希望白嫖完之后,每个时刻的未处理的流总量是差不多的。以每个时刻按照“未处理的流总量”推入堆,每次弹出一个流总量最多的时间进行处理。 -- 这个效果不好
对于后95%:节点白嫖完之后,将尚未被处理的流继续分配给节点,此时流的大小决定着95%的成本。我们需要使每个节点的95%尽量小。可以想到“均分”和“牺牲”两种方法,均分即把剩余流尽量均匀的分配给节点,牺牲即使得若干个节点的成本尽量大,其他节点成本尽量小。提交得均分效果更好。
具体操作:将流从大到小排序,先处理大的流,放入节点后标记该节点成本为流的大小lmax,使得后续在其他时刻放入该节点的流总和不要超过lmax。但是存在不得不超过lmax的情况,这时要遍历所有节点,将其放在“使得成本变化最小”的节点内。
其他改进:分配完之后再调整。分配完之后可以得到每个节点的成本序列,可以遍历每个节点的95%号位内的所有流,看能不能把流转给其他成本低的节点,使得总成本下降。(这个方法对我们的效果不明显,因为我们的94%号位很靠近95%,需要遍历N次调整才能降低一点点)
也可以考虑二分图完美匹配、最大流等算法,但贪心足矣,主要考虑排序规则和处理的思路,我们最大的改进就是后95%的max操作,总成本从91W降到了52W。