1. 华为2019软件精英挑战赛
主要思路:
(1)佛洛依德最短路径算法
(2)快慢车道(根据速度按批安排发车时间)
(3)对道路出现拥堵的车道修改部分车的接下来的路径规划,往空闲车道进行分流。
最大的难点:
1.复杂的交通规则。
路口相遇的各种优先级,各个车道的优先级,各条道路的优先级,需要按照车道id顺序排车,此外过交叉路口的转向规则也基本按照现实交通规则执行:让右侧道路车辆先行,直行先于转弯,对向行驶的右转的车让左转的车先行。导致判题器(即每一个时间片各个车辆按照设定的交通规则在规划的路线上接下来将移动到哪一个位置)实现难度比较大
2.车辆死锁的处理。
解决思路是回滚到上一次备份时刻重新设计部分车辆的路线,多次死锁还可能触发延长部分车辆的发车时间。(如何判断死锁发生:如果在一次时间片调度中,所有的车都因为冲突而不能前进,则认为发生死锁)
(1)弗洛伊德算法
需要两个数据结构:dist[i][j]表示i到j的最短距离,path[i][k]表示i到j下一步要去的节点
三层for:
//使用弗洛伊德核心算法,三层循环求解
for (k = 0; k < G.numVertexes;k++){ //中间节点
for (i = 0; i < G.numVertexes;i++){ //起点
for (j = 0; j < G.numVertexes;j++){ //终点
if ((*dist)[i][j]>((*dist)[i][k]+(*dist)[k][j])&&i!=j) { //i!=j使不更新中间自己到自己的数据和路径
//将权值和更新,路径也变为中转点
(*dist)[i][j] = (*dist)[i][k] + (*dist)[k][j];
(*path)[i][j] = (*path)[i][k];
}
}
}
}
迪杰斯特拉算法
需要两个数据结构:dist[j]表示起点到j的最短距离,parent[j]表示起点到j的上一个节点
两者的主要区别----Floyd算法是计算所有起点到所有终点的最短距离,Dijkstra是计算指定起点到所有终点的最短距离。
(2)调整发车时间
数据集上绝大部分车的发车时间相差不大。
策略是让车速相近的车辆在同一个时段发车:对车速划分区间,速度越小的区间,获得的惩罚加时越长。
(3)根据拥挤度重新调整接下来的路径规划
时间片运行过程中,如果检测到某些道路出现严重拥挤(定义:道路的车数目超过所有车道上车的平均数的2.5倍,就认为严重拥挤),将时间回滚50个时间片(我们的备份策略是每隔50个时间片备份一次,当然50可以调整,备份是当前时刻所有道路上的车辆位置和各车辆的路径规划),并对拥挤道路增加惩罚权重,对之前出现在拥挤道路的车辆重新规划车辆所在道路与他们的终点的最短距离,继续运行。
(4)修改死锁车辆的路径规划
什么是死锁?
因为交通规则的限制(在交叉口如果要去的道路最末尾所有车位在下一时刻仍然全部被占,则该车需要等待。此外通行规则限制:左转让对向的直行,右转让对方向左转和左侧直行的车辆,转弯让直行,车道排车顺序要根据车道顺序整个车道安排完后接着安排下一个车道上的车。因此交叉口等待会可能造成死锁。)
如何处理死锁?
回滚。
恢复到50个时间片之前,对部分交叉口路口准备出路口的车辆设置对应道路为禁忌道路(惩罚一个很大的权重),重新规划接下来的路线。如果再次死锁,则回滚到100个时间片之前。如果多次死锁,重新安排死锁车辆的发车时间,对车辆原有的发车时间上增加一个随机时间,尽可能避开死锁,而最极端的情况就是会造成死锁的车辆一直等到最后才被安排上路,最后一批到达车库。
源代码:https://github.com/eaglesunshine/Huawei_CodeCraft-2019
2. 华为2019网络精英挑战赛
比赛是单人赛。
初赛是知识竞赛,笔试的形式。
复赛赛题是手机号码的选号系统,在给定头文件下,自己设计数据结构,实现如读取并检查文件中的号码信息、号码信息查询(价格、品牌、状态)、自助选号(比如要124开头或者要779结尾的号码)等接口。
难点:限制了头文件,不可自行新增头文件,一些方便好用的库使用不了,比如algorithm、regex等。
结果:2个小时内基本完成了各个接口的开发,并通过了现有的所有测试样例。
3. 华为2020软件精英挑战赛
初赛赛题:给出一批转账记录,找出其中的循环转账路径,要求转账路径长度大于等于3且小于等于7。
初始思路:根据输入构造每个节点能够到达的节点序列,按序遍历每个节点能到达的路径,直到路径出现第一个与头元素相同或者路径长度大于7,当条路径遍历终止
。
源代码:https://github.com/eaglesunshine/CodeCraft_2020
优化版本:
由于搜索中存在大量冗余,而且输出中环路按字典序输出,可以联想到去重和排序并不是必须的。考虑1->2->3->4->1的一条环路,在以2为起点时,同样有等价的环路2->3->4->1->2。在搜索中,这两次是冗余的
。
同理可推导知:在搜索过程中,邻接点中只需要遍历比起点id大的节点,这样即可省去去重
;在搜索前对邻接表排序,即可省去排序。
源代码:https://github.com/ZhangJ-Roykin/HUAWEI-codecraft2020
4.华为2021软件精英挑战赛
赛题:
给定一批服务器种类和虚拟机种类,每批测试数据是连续N天的虚拟机任务请求,包括add请求和del请求,你需要安排购买哪些服务器,何时购买,以及考虑每天对虚拟机任务的迁移,使得所有虚拟机任务跑完所耗费的服务器硬件成本和总能耗成本最低。
解决思路:
主要采用了贪心的策略
算法主要步骤可以分为三个部分:1.购买新服务器;2.选择旧服务器;3.虚拟机迁移
-
购买新服务器
当机房内为空或者现有服务器无法满足add的虚拟机任务时,需要购买新的服务器来放置虚拟机任务。
选择“硬件成本+剩余天数能耗成本”最低的进行购买
。 -
选择旧服务器
当现有服务器可以继续容纳add的虚拟机任务时,选择从旧服务器中选择放置虚拟机任务。
对两个del任务中间的add任务按照资源占有量从大到小排序,优先调度资源占有量大的虚拟机任务
。
对于每个add任务,对现有服务器按资源利用率排序,优先选择资源利用率高的进行配置
。 -
虚拟机迁移
每天允许迁移虚拟机数目为当前虚拟机任务数的百分之三以内,即将虚拟机任务从一台服务器迁移到另一台服务器。
执行两层迁移:
第一层:基于能耗的迁移
。将能耗高的的服务器内的虚拟机尽量迁移至能耗低的服务器中。
第二层:基于利用率的迁移
。将资源利用率低的服务器尽量迁移至资源利用率高的服务器中。