引子

先解释一下队名rOtp。对于华为软件精英挑战赛来说,我们已经算是老司机了,去年我们以队名“写bug小王纸与找bug小公举”初次参赛,折戟总决赛的16进8环节,与奖金失之交臂。同组第二名在落后了整整一下午的情况下,在最后十分钟提交了一份代码,完成了绝杀,我们被打到第二,淘汰赛首轮就不幸对阵到了最终的季军队伍,最终铩羽而归。这次失败经历给我留下了沉重的打击,我不服,明年我们还要来。rOtp的名字是队长起的,借鉴了dota战队rOtk的命名思路,return of the prince,即王子归来,看到队名后我们一拍即合,干!顺便解释一下我们的团队口号,“身无彩凤双飞翼,心有灵犀一点通”,一句诗中包含了我俩女朋友的名字,真是天意啊233.

初赛

初赛的题目就不赘述了。我们将去年的失败的遗憾全部转化成了对今年比赛的重视,2号,比赛群里流露出了疑似今年的赛题,后经证实是网站GG的操作失误,被手快的童鞋爬下来了,第一眼看到题目,感觉和去年的题目好像,也是一个类似寻路的NP问题。根据去年比赛经验的直觉,我判断启发式算法太难求到最优解,求到了也难以停止迭代,加上去年对线性规划求解器的研究,对线性规划解此类问题已经不再生疏,当机立断采用线性规划。2号晚上,我们建好了模型,写出了线性规划matlab第一版。3号中午官网正式发布赛题,两个小时以后,我们就利用官方SDK完成了c++的第一版程序,几百毫秒算出了所有case的最优解,当所有人还在研究题目,研究费用流和启发式算法时,我们走上了优化模型和手撸求解器的不归路。手动给队长钱坤大佬点赞,独立完成了一套对偶单纯形+分支定界+gmi+mir割平面的线性规划求解器。当初建好模型给他,他就和我说,就搞线性规划,求解器你放心,交给我。对于队长的这份魄力和编程能力我是十分敬佩的,毕竟要是这份工作放在我面前,我是一行都敲不出来的,笑。

复赛后面大佬们经常用的DSSP思路我们在初赛也尝试过,解初赛问题效果不是很好,只能得到一个比较一般的近似解。要知道,当时大家都在追求最优解,这篇文章就被我们扔到一边去了。参考文献:A solution approach to the fixed charge network flow problem using a dynamic slope scaling procedure。

初赛模型

目标:成本最小

约束:整数约束;带宽约束;消费流量约束;链路约束。

Tips:
1.超级源:引入虚拟源节点0,Cy为内容服务器成本
2.消费节点压缩:根据每个网络节点最多仅能连接一个消费节点,每个消费节点仅能连接一个网络节点。第一步必然是缩小拓扑,对消费节点进行前向压缩,将消费需求压缩到网络节点中,即该网络节点有相应的带宽需求。后来大家所说的在消费节点建服务器指的就是压缩后的有带宽需求的网络节点。

模型
Minimize:

min⁡z=∑i=1n[∑j≠i,j=1n(uij⋅cij)+sic0i]\min z=\sum\limits_{i=1}^{n}{\left[ \sum\limits_{j\ne i,j=1}^{n}{\left( {{u}_{ij}}\cdot {{c}_{ij}} \right)+{{s}_{i}}{{c}_{0i}}} \right]} minz=i=1∑n​⎣⎡​j​=i,j=1∑n​(uij​⋅cij​)+si​c0i​⎦⎤​

Subject to:

节点流量约束

∑j=0,i≠jn(uij−uji)−abilityi∗si≤−di\sum\limits_{j=0,i\ne j}^{n}{\left( {{u}_{ij}}-{{u}_{ji}} \right)-abilit{{y}_{i}}*{{s}_{i}}}\le -{{d}_{i}}j=0,i​=j∑n​(uij​−uji​)−abilityi​∗si​≤−di​

链路带宽约束

0≤uij,uji≤bij0 \le {u}_{ij},{u}_{ji}\le {b}_{ij}0≤uij​,uji​≤bij​

−∑i=1nabilityi≤−∑i=1ndi-\sum\limits_{i=1}^{n}{abilit{{y}_{i}}}\le -\sum\limits_{i=1}^{n}{{{d}_{i}}}−i=1∑n​abilityi​≤−i=1∑n​di​

abilityi=∑j=1nbij+di{{ability}_{i}}=\sum\limits_{j=1}^{n}{{{b}_{ij}}}+{{d}_{i}}abilityi​=j=1∑n​bij​+di​

其中,b为每一条边的带宽限制,c为每一条边的成本,u为每一条边的带宽使用情况,uxy和uyx不一样,区分先后顺序,d为每一个网络节点的带宽需求,s为是否在某点建立服务器,为01变量。

写公式太麻烦了。。。各种bug。。。就这样吧。。随缘懂。。

初赛第一次放线上用例时,模型的过于简陋加上求解器效率问题我们case1需要80s才能迭代结束得到最优解。建模过程中,除了对求解器的优化,优化模型也可以大大提高求解速度。

首先,对边流量变量设置为连续变量也可以自动求出整数值,去掉对边流量的整数约束,时间80s->30s。

然后通过降低大M法中大M的取值来降低线性规划的下界,用时缩短到了30s->10s。大M法中的大M就是模型中的ability变量,一开始我们草率的设成了100000,影响了求解效率。大M法的介绍见此链接目录第一条。

最后,利用流量间的守恒关系去掉了所有的等式约束,将其与不等式约束进行了合并,这一优化直接减少了点数个变量和边数条约束,求解效率大大提升,最终耗时10s->4s。上文所给的模型已经是合并后的模型。

之后再想优化就都是有风险的优化了,可以大大提升求解速度,但是可能会损失最优解,好在我们可以不停地上传调参,以达到又快又准。制约线性规划速度的最大因素就是分支定界,简单的说,在求整数问题的松弛问题时(忽略整数约束),每求到一个非整数变量如0.7,我们需要把这个变量分成0和1,建立两个子问题重新求解,由于问题是线性的,在子问题的求解时,已被分支的变量会自动求成整数,再继续对其他变量进行分支。因此整数变量的个数越多,这颗搜索树越深,遍历搜索树的速度越慢。解决这一问题最直接的方法就是减少整数变量个个数。其物理意义就是,在所有网络节点中筛选出一个服务器候选集,只有在服务器候选集中的网络节点有资格建立服务器。候选集建的越小,求解速度越快,当然,在小的同时,不能筛选掉最优解中的服务器。

对与候选集,我们先对所有消费节点两两算一次spfa,记录亮亮消费节点最短路径所经过的点,统计每个点出现的频次,对出现频次高的点纳入候选集。当然还有其他参数如出入度,出入流量和等。这些都是参数,优化就是不停地调参提交,就不一一列举了。最后我们发现,线上的例子最优解服务器全都在消费节点上,也就是用所有的消费节点当候选集。最后两题都是100ms出解。。呵呵。。

线性规划的方法相比于大多数人的费用流+启发式可能思考的方向不太一样,由于之前也没接触过,也就研究了短短一个月的线性规划,可能模型里还有很多没有优化到的地方,表述也可能有误,请不吝指正。

当然了,初赛的算法还是比较粗糙和传统的,小图由于可以算到接近最优虽然速度比较慢但成绩勉强凑活,到最后八百点的图的时候已经计算规模已经远远超出我们的计算能力,有时候只考虑消费节点做候选集都有可能90秒算不出解,初赛最终掉到了第六。不提了,说多了都是泪。

复赛

复赛的赛题又一次增加了拓扑规模,顺便增设了十个服务器档次,如果每一个档次都对应一个整数变量的话,也就是整数变量也乘以十掐指一算,变量数炸了,我们的心也炸了。初级案例都是清一色的超时,我们开始质疑当初初赛的选择,开始考虑后路,队长不愧是队长,用了一天撸了一个网络单纯型,又用了一天撸出来一套差分演化的启发式框架,效果嘛,中游吧,说他弱吧,也能排前几,说他强吧,离我们的目标还有一定的距离。

中间我们还尝试过benders分解。bender分解将混合整数规划问题分解成整数规划部分和非整数规划部分两个部分,通过互相迭代收敛。非整数部分恰好就是传统的费用流问题,可以用网络单纯型求解。刚看到benders分解的相关文献时,我们都很兴奋,按照论文所获,这简直是为这道题目量身定做的一套解决方案,线性规划+高速的网络单纯型相结合,两者相得益彰,有种相见恨晚的感觉。但是用了几天实现以后发现效果并不好,上界收敛太慢(还是下界来着,记不太清了)。有兴趣的同学可以研究研究,如果有其他队用了这个方法也可以和我们沟通沟通,看看是benders分解的通病还是我们自己的实现问题。

听说DSSP在复赛显现出了威力,只可惜它在初赛时给我留下了非常不好的印象,虽然也曾经想到过试试DSSP,不过也仅仅存留在计划之中了,始终没有动力再去实现一个已经被我否定了的算法。

后来。。。我们对线性规划进行了魔改。。。中大规模基本都能算到里最优解误差1000以内。。。经常能比赛区第二cost低一两万。这里卖个关子,挖个坑以后来填or等队长去填。最后有惊无险的以赛区第一晋级,听说最后全国排名也是第一,不过没得一百分还是有些遗憾的。

个人信息里的成绩被清空了,没有cost截图了,从聊天记录翻到一个文字版的。
0 249379 88322 19.44
1 195885 88159 20.00
2 393215 89013 30.00
3 424572 88594 30.00

#决赛 #
决赛的问题十分有趣,和初赛复赛关系不大,是一个两两PK的博弈问题,为了保证PK的公平性,每次PK五个图,并且采用联赛一样的积分赛。两个星期的时间稍显仓促,不过,大家都很仓促,大家决赛练习赛藏代码的保守态度,给比赛带来了很多不确定性,测试机会稀缺,每个人的心里都没底。

两次模拟排位赛我们都因为bug失去了自我定位的机会,在bug面前,再好的策略都等于认输,这也让我们急的焦头烂额,最后一周基本是在与判题组的沟通中和找bug中度过的,再也无心优化策略,直到抵达深圳,决赛现场赛的前一晚,才静下心来通宵理了一遍代码,改出了很多bug。。。

我们的决赛策略分为两个部分,初始解部分和迭代部分。和上合赛区AFH战队的讨论中,我们理解到了初始解和投资上界的重要性。投资上界是指一个消费节点的所有邻边的出度之和。地图上存在不少的点,比如需求为1,上界为5。这种点直接投资5个流量是稳赚不亏的,顶多平分利润。

聪明一点的流量需求+1,更聪明一点的+2,我们直接加到上界。

当然,在交流中我们发现,+1被+2克,+2被+3克,反过来,加到上界由于占得的点数太少,也可能被直接+0的完败,所谓小卒子扳倒老帅。为了避免这一情况的发生,我们将上界从小到大排序,使得初始解中达到上界的点占初始解的三分之二,刚好满足需求的点占初始解的三分之一,这样初始解既达到了一定的强度,也达到了一定的广度。在测试过程中,这样选出来的点比全部刚好满足需求的选点数量少不了多少。至少可以保证我们在第一轮中利于不败之地。

在迭代过程中,我们实现了一个非常复杂的状态机,复杂到可能会状态乱窜,不按我们想象中的流程去执行,决赛完了我们也不忍心再去看代码了,怕发现漏洞以后心痛= =。

每次迭代中,对于每个点存在一下几种状态:我们占了占到的,我们占了没占到的,我们没占对方也没占的,我们没占对方占了的。每一个状态都要单独考虑。

对于我们占到的点,我们选择了不加流量继续占,队长曾考虑过增加流量,也写了一个粗糙的版本,被我改回来了。。。专家在这点上在PPT中对我们进行了批评,说我们的防守策略不够好,现在再想想,这里确实不妥,应该在赚钱了的基础上继续曾加流量,或许结果可以更好。对于我们占到的点,可能是以较高代价占的并且由于我们的流量过高对方没有尝试或者已经放弃。AFH战队提供了一个很好的偷鸡策略(专家很友好的在PPT改成了投机),即连续n轮占得某点以后,直接用最低需求(由于是预判对方已经放弃改点,一定要用最低需求去偷鸡)去尝试占该点。一旦偷鸡成功,赚得盆满钵满。即使碰到头硬的队伍偷鸡失败(被反占),回调流量或回调一半流量即可。偷鸡策略几乎没有破解策略,对方的服务器设置使得对某个消费点提供的流量达不到我们所能提供的流量,就只能眼睁睁的看着我们偷,头硬一直尝试,会亏得更惨,毕竟扑空的概率更高,除非测出我们的偷鸡触发条件,这太难了,毕竟我们会根据偷鸡成功率(对方的头硬程度)动态调节n值。

对于我们占了没占到的点,我们会对当前流量再加一个值,这个值是浮动的,根据历史成功率变化,成功率低了值会抬高,成功率过高会降低,最终保持在一个稳定的状态,如成功率90%左右,也算是一个滤波器吧,强行往冠军的思路上靠- -。另外,由于我们计算了每个点的流量上界,一旦判断该点的流量达到了上界,就会进入战斗状态,战斗状态是一个特殊状态,由于战斗状态至少流量打平,处于战斗状态的点我们会一直占有,直到触发偷鸡条件,判断对方已经放弃改点,进行降流。

对于我们没占对面占了或没占的点,这两个的处理思路是很类似的。可以换位思考一下,对于这些点,对方上轮占有成功或这轮准备占有时,是把他当成一个中立点进行占有的,一般都是+1+2或者+n或者动态调节。我们也会通过计算占有这些点的成功率来估计对手所加的值,从而动态调节我们所加的值,使得对这类点的占有成功率保持在90%左右。当然这里的成功率计算和上面的成功率计算都是不考虑已经进入战斗状态的点的,这也是要单独设立一个战斗状态的原因。

终止迭代方面,我们基本上是计算新建服务器能否收回成本,一般在四十轮左右就停止迭代了,这里考虑的不是非常周全,也没有时间去细细考虑了。

决赛策略暂且想到这么多吧,要是发现有遗漏的地方,以后再补充。

#一点感想#
首先必须安利一波华为公司。虽然比赛过程中出过一些问题,但是可以看出比赛过程中每一个工作人员都非常努力,非常热情。菊厂还是十分土豪的,比赛过程中各种暖心的设计,有趣的项目,参加复赛和决赛全程报销,奖金也十分可观,可见一个大企业的底气和对人才的重视和渴望。

不论是上研所还是深圳总部,都对我们的想法给予的充分的支持,在进入决赛后,帮助我们和导师沟通,帮我们和导师请假,帮我们安排专家和集训,让我们有了充足的时间和精力去只做一件事,我已经好久没有这种充实而又不感到累的感觉了,比赛结束后,面对实验室的烂摊子,感到十分空虚- -。

队友很重要,抱大腿很重要。决赛赛题刚出的时候我很迷茫,加上实验室师兄和导师的push,我无心准备比赛,队长表示理解,让我安心先做好实验室工作,做完了再去搞比赛。队长的导师就很支持他们搞比赛,甚至非常关心我们的比赛进程,也会在组会上发动大家的力量群策群力。羡慕这样的导师~

交流很重要。去年我们进入决赛以后一直是闭门造车,连赛区内的兄弟战队都没有任何沟通,最终错误判断了形式,葬送了好局。今年我们虽然也会偶尔藏藏代码,但也会一直和群里比较活跃的同学保持沟通,交流算法和心得,受挫的时候也会互相鼓励。感谢同赛区的AFH,WoW,赳赳武夫,他乡的咸鸭蛋,围墙编队,USTC601,Kappon,要优雅等,感谢其他赛区的秋香,月光,吴亦凡,追日~在大家都在藏代码保留实力的日子里,我们坦诚相见,毫无保留,才能在不断进步的队伍中不被落下。

感谢自己的女朋友,连着两个月没怎么好好陪她了,发朋友圈也忘记感谢她了,嗯。。。

链接一发月光的博客
http://blog.csdn.net/luanshaotong/article/details/72255469

2017HW软件精英挑战赛总结相关推荐

  1. # 2021华为软件精英挑战赛C/C++——build.sh/build_and_run.sh/CodeCraft_zip.sh注释

    2021华为软件精英挑战赛C/C++--build.sh/build_and_run.sh/CodeCraft_zip.sh注释 1.build.sh #!/bin/bashSCRIPT=$(read ...

  2. 2021华为软件精英挑战赛(附赠线下判题器链接)——经历

    2021华为软件精英挑战赛(附赠线下判题器链接)--经历 1.题目解析 本次赛题源自现实的互联网企业面临的问题,怎样购买与部署服务器最便宜! 服务器:不相同型号的服务器有着不同的CPU与不同的内存,每 ...

  3. 海康威视2017软件精英挑战赛初赛题目

    题目概述 在车库中安排若干泊车机器人,根据给定的车位地图,合理优化机器人的数量及其运动路径,尽量减少客户在停车和取车中的等待时间,并使总成本最小.(试题用例包于5月初开放下载) 参数设定 为了简化问题 ...

  4. 2023华为软件精英挑战赛,探寻软件人才与科技创新的最优解

    作者 | 曾响铃 文 | 响铃说 今天,软件行业正呈现出江河入海一般的大汇流趋势. 一方面是技术的汇流,诸如人工智能等前沿技术与软件行业的深度融合,正全面颠覆软件产品的开发模式和服务逻辑. 另一方面则 ...

  5. 华为2020软件精英挑战赛初赛、复赛、决赛代码+心得分享

    目录 写在前面 初赛 第一代思路 第二代思路 最终版思路 优化思路 多线程 数据结构设计 输入和输出的优化 复赛 规则描述 优化思路 算法 多线程 数据结构设计 复赛正式赛 总决赛 总结 写在前面 2 ...

  6. 2016华为软件精英挑战赛:赛题及其答疑汇总

    注:本文文字均摘自官方指定网站和论坛,权威且可信,答疑见中间部分,非常全,众玩家可放心阅读. 同时文末给出了包括自己在内的诸多玩家的解法. 前言 赛题源自"未来网络"业务发放中的路 ...

  7. 2021华为软件精英挑战赛,思路框架,欢迎留言讨论

    2021华为软件精英挑战赛,思路框架. 1.对数据初始化封装 服务器 用集合来进行封装,集合由字符串和数组组成键值对 {"服务器型号":[cpu内核,内存,硬件价格,能耗]} 例如 ...

  8. 2021华为软件精英挑战赛(杭厦第20名)

    写在前面 距离华为软件精英挑战赛结束也有一段时间了 我是浙工大投降战队的队长,第一次参加这种比赛能打到复赛我还是比较满意的 这次比赛我最大的收获就是认识了好多厉害的大佬 希望我们杭厦赛区晋级的战队总决 ...

  9. 华为2021软件精英挑战赛复赛赛后方案分享

    华为2021软件精英挑战赛复赛赛后方案分享 引言: 赛题介绍 资源规划和调度 输入示例: 输出示例: 总体处理流程 部署策略 购买策略 迁移策略 赛后感受 开源代码 引言: 我是来自成渝赛区UESTC ...

最新文章

  1. Android中Messenger进程间通信
  2. 剑指offer第二版答案详细版(带详细解题思路)
  3. 一个按钮,如果5分钟内点击再次点击给予提示操作频繁,在JS里可以这样写
  4. 浅谈 maxMemory , totalMemory , freeMemory 和 OOM 与 native Heap
  5. C 的 3种内存顺序,你都知道吗?
  6. 【Python - GPU】基于Python的GPU加速并行计算 -- pyCUDA
  7. java dispose null_Java Map释放内存置null以及调用clear()的区别
  8. 生成交叉表的SQL基本语句
  9. 百度豆丁文档免费下载神器
  10. java oa系统消息推送_第三方系统向泛微OA系统推送消息
  11. 高级软件工程课程总结
  12. 如何用python写脚本_python写脚本
  13. 导致页面布局混乱的几个元凶
  14. 使用echarts画日历热力图
  15. 计算机工作原理【操作系统和进程】
  16. mysql查询所有学生各科成绩按照总成绩降序排列
  17. 无人值守系统安装--自己的系统实用篇
  18. win10打印机安装提示无法连接到打印机
  19. Hyperlynx DDR SI 仿真分析技术 | IBIS 模型适配
  20. 如何配置一个极简舒适的终端环境:oh-my-zsh 和iterms配置

热门文章

  1. Komodo Edit快捷键
  2. 基于Python的Opencv 自动识别银行卡卡号系统
  3. dy极速版2-艳云脚本云控系统
  4. 古今群侠传java,【古今群侠传官网版】古今群侠传最新官网版下载_66游戏网
  5. android 一键锁屏和清除手机数据
  6. EAS 系统子系统树
  7. 128g内存linux开机需要多久,10年时间内存的变换,128MB到128G,价格不但没涨反而越来越低...
  8. 微信开发工具常用快捷键
  9. python爬虫爬取B站【马保国】诶..朋友们好啊,我是混元形意太极门掌门人——马保国,独自一人撑起了B站2020年的年尾。
  10. 北京国税办税软件安装问题