2022华为软挑赛题讲解(CodeCraft-2022)


  代码链接附在文后,赛题解释权归华为所有,本苟弱对赛题的讲解不一定是完美的,有任何不足和错误欢迎大佬们斧正~

一、赛题任务书简述

  总的来说是视频直播流量调度的问题,具体的任务书已上传到github上,有需要的可详细看一下任务书中的细节,这里只对任务书的需求做简单阐述。
  初赛: 任务书给出边缘节点的带宽上限、qos上限、每时刻(每隔5min算一个时刻)中客户节点在该时刻对流量的总需求,每一个时刻都需要在满足带宽和qos上限的情况下将客户节点分配给边缘节点,分配后的边缘节点对每个时刻所分配的流量升序排序,按排序后的取后5%的时刻作为免费时刻,95%(向上取整)的位置作为95计分点。
  复赛: 在初赛的基础上,将客户节点的流量离散成多种流,会分别给出每一种流在 t 时刻时全部客户节点对该种流的需求量是多少,每一个时刻的流量种类可以不同。正式赛的时候,基于练习赛,变更点是可以任选10个边缘节点,将他们的计分点改为90%的位置,其余的边缘节点仍然是95计分点。
  决赛: 在复赛练习赛的基础上,增加了中心节点和每个时刻的缓存机制。每个时刻中,边缘节点向中心节点请求的某种流量为这种流在该边缘节点的最大值(所以需考虑聚合流),边缘节点的前一个时刻所占用的带宽5%(下取整)会叠加到下一个时刻的带宽用量(但不会影响向中心节点请求的带宽量)。正式赛的时候,变更点是可任选20个边缘节点将5%的缓存机制改为1%的缓存机制(下取整)。

二、解题过程

  贯穿初赛到决赛的过程中,top5%的处理是最为重要的,尽可能多去白嫖top5%,然后将95%选择好让95计分位不要太大,最后再考虑迁移或者迭代。
  初赛: 拿到赛题的时候,我们基于均分出了个baseline,但看排行榜很明显是有更优的操作,在水群的时候也吸收了一些大佬们的思想,我们先后尝试了网络流(费用流)、硬贪的方法。
(1)网络流,就是对问题的抽象与建模,建立一个超级源点S与超级汇点T,S连E(边缘节点层)、E连C(客户节点层),C连T,但是存在个比较重大的问题 “如何根据任务书的公式抽象费用” ,最后经过多处求证得出的结果是不能精确建立起费用,只能将费用转换为优先级进行建模,这就是网络流的一个缺点。果然最终的效果虽然跑了了40多w的分,但这已经是最大限度的优化了,而且耗时也巨大,所以我们决定换成硬贪。
(2)硬贪,总的来说就是找准选边缘节点的优先级,本着削峰的思想,先按全部时刻找需求量最大的top5%,然后边缘节点按带宽上限从大到小排序(当带宽上限相同的时候,我们是随机排序的),接着逐个遍历边缘节点选好top5%。top5%选好后,先构建一个数据结构维护95计分点,然后分别遍历下每个客户节点可连接的边缘节点,选一个对边缘节点95计分位影响最小的来放该客户节点的流量需求。
  在初赛我们就根据硬贪和加了些优化,此时还没加上迁移,跑出来的耗时也比较可观(具体是多少我忘记了),初赛以训练赛rank10&正式赛rank19成功进入复赛。
  复赛: 到了复赛很多人都懵了,相对之前的软挑,这次改动是算比较大的,很多人都要重新写一版代码,特别是用了网络流的,网络流不能解决这个流离散的问题。因为每个客户的流量需求从总需求变成了多种流的具体需求,增加了离散性,输出的格式也从 <边缘节点,客户节点> 变成了 <边缘节点,流种类1,流种类2……>。我们的策略进行了更新和优化,增加了维护边缘节点每个时刻分配了哪种流的数组,增加了迁移策略,最重要的是优化了下top5%的选择。
(1)5%策略,具体可以结合我们代码看看,先遍历下该边缘节点所能连的全部客户节点,再遍历下该时刻的全部流,top5%的策略是“连接度优先的思想”(即每一种流都可放到不同的边缘节点,能放的越多边缘节点说明连接度越大),统计每个时刻的连接度总和,选取总和较大的top5%时刻。
(2)迁移策略,我们有想过根据迁移策略特殊ban掉某个边缘节点,以实现成本全0化,但经过测试发现这是行不通的。最后迁移的原则就是尽可能的使95计分位贴近basecost,将95分位较大的往较小的去迁移,较小的只能贴近basecost。
(3)正式赛,按带宽上限从大到小排序,选取10个带宽上限较大的作为90计分位的边缘节点。这样选的原因是尽可能的放更多的峰值流量。
  复赛正式赛的时候因赛题方的判题器有问题(估计是写成向下取整了,任务书要求的是向上取整),导致是以第12名未能进决赛。但是后面有一个复活赛,这次赛题方把错误改过来了,最后以68w的分数全赛区rank2的成绩进入总决赛。
  总决赛: 增加了一个中心节点和缓存机制,这个时候就要考虑“聚合流”(每个时刻将同种流尽可能的放到同一个边缘节点上)的思想,同时因为缓存机制的问题所以top5%不能直接塞满,5%要分成非严格的2.5%来塞,也就是说先塞完2.5%,剩下的2.5%就是留给之前那2.5%的下一个时刻。正式赛的时候,变更点的策略就是选取5%的前20个边缘节点,因为之前选的5%是带缓冲的,所以代价不会太大。最后可能在于调参方面我们做的不够好,优化的细节可能也没到位,听说总冠军是调参上去的这就很搞人心态。

三、心得体会

  和小伙伴们打华为软挑收获比较多,玩的也比较开心,然后还能和一些不错的伙伴进行交流,当然水群的过程中也能学到不少的知识。华为软挑算法优化的过程中也要讲究时间的优化,因为要拿时间给迁移或者迭代,所以抽象题目并建立一个好的数据结构也比较重要,赛题中95分位比较难维护,特别是多了个中心节点后,但是我们采用了 set 的数据结构解决了,同时因为 set 的内部排序原因,这也使得我们的时间复杂度大大降低。打比赛主要是想增加自己的见识,当然能够以一定的技术能夺奖也是挺好的,当然总决赛的前几名除了讲究技术还要讲究运气的,说不定某些时候突然有了神奇上分的trick,一下就可以进步很多。
  我们的代码已放到github上,有需要的可以自取研究看一看,代码并不完美,可能有比较难读懂,发现代码有任何问题的可以及时指出,支持的话希望能给个⭐,欢迎各位大佬来斧正~o( ̄▽ ̄)o

代码链接:https://github.com/HuangTingXuanA/codecraft-2022.git

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ac君

在你们的鼓励下我会多多分享代码

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值