2019年3月参加了华为软件精英挑战赛,过程很刺激,西北赛区真的强,最后成绩:西北赛区初赛第四名,整理了比赛的过程跟代码,分享给大家~~
题目描述
背景信息
日常生活中,很多拥堵是由于车辆行驶路线规划失误,大批车辆集中选择主干道行驶导致通行效率下降。
如果车辆都由调度中心统一规划调度路线,拥堵问题将得到大大缓解甚至彻底解决。
实际上这一技术已经在工业领域如矿山车辆、无人货仓等得到广泛应用。
但道路上的私家车辆尚无法进行统一规划,未来,自动驾驶和物联网技术的结合,使得彻底解决这一难题出现了曙光。
请同学们提前出任“首席城市交通规划官”,为未来城市规划好每一辆车的行驶路线。
假设条件
路口完全立交:假定在每一个路口交汇的所有道路都可以完全互连,且车辆通过路口时不考虑在路口的通行时间。
无限神奇车库:我们认为,系统中的每个地点都有一个无限容量的“神奇车库”。车辆在未到既定出发时间前,或者到达目的后,就停放在“神奇车库”中,完全不影响其他车辆通过。但车辆一旦出发,在行驶过程中则不允许进入车库空间。
不允许超车变道
排队先到先行
车道固定进入
题目输入
每一个测试用例都分为三部分:
road.txt/car.txt/cross.txt
1 | 道路:(道路id,道路长度,最高限速,车道数目,起始点id,终点id,是否双向) |
图形化实例:
答案提交
要求为每辆车规划最短路线,输出answer.txt
1 | (车辆id,实际出发时间,行驶路线序列) |
评分标准
系统调度时间短者胜出。系统调度时间指,从系统调度开始时间(非第一辆车实际开始运行的时间),至所有车辆全部到达目的地的时间,两者之差作为系统调度时间。
若系统调度时间相同,则所有车辆的行驶用时总时间最少者胜出。
解决方法
建立一个矩阵,表示每条路的拥堵程度:
[道路长度]+[每条路当前时刻正在行驶的车辆数/车道数],按照一定的权重比求和
矩阵的大小都是cross*cross
对新矩阵中的每个点做floyed,求出其最短路线。
其中,在计算每条路当前时刻正在行驶的车辆数时:
对已经规划好路线的车辆,每条路的长度/车辆速度(不能超过道路最大速度)=每条路上花费的时间
知道了出发时间,每条路上的时间,就可以计算出当前时刻所在的道路,在矩阵中该路线的位置加1
每秒发n(初赛62,复赛80多)辆车,这个n的值是调参调出来的不出现死锁的最大发车数量
Floyed最短路径算法
Floyd算法是解决任意两点间的最短路径的一种算法,是一个经典的动态规划算法。
上图表示是几个结点,以及结点之间的距离,上图的信息可以用一个矩阵来表示:
比如求取i到j之间的最短路线,找到i和j之间的结点k,判断
1 | for (i=1; i<=nv; i++) |
求i到j之间的距离,先找到第一个结点k,判断加入k之后距离会不会变小,如果变小,再求k到j之间的最小距离,在找到第二个结点k…依次循环
其他方法
将速度大的车选出来,放在一个组,让他们先发车,因为速度大的车先发,就会先到终点,会减少后面道路的拥堵程度,但是效果并不好。
分析原因:可能是让速度大的车先发了,后面的车都是速度慢的,整体来看,道路可能更容易堵。让速度大的那组,一次多发一些车
行车方向相近的,分在不同的组,避免造成拥堵
复赛
复赛加上了优先车辆跟预置车辆的约束条件,优先车辆可以优先使用道路的路权并且先发车,预置车辆是指道路已经确定不能修改的车。
处理方式是:最终的评分标准中,总系统调度时间+优先车辆的时间
优先车辆:先发车,还是按之前的方法求出每辆车的最短路线
预置车辆(3000辆左右):跟普通车辆一起发,在发车前进行一个if判断,如果是预置车辆,则按照其路线发,如果是普通车辆,就跟之前一样的处理方式。
遇到的问题
题目要求程序运行时间900s=15min,但是我们的python运行时间是半个多小时,最终翻译成c++程序就只要几分钟,时间大都浪费在floyed运算上面。
遇到瓶颈,无法继续优化路线,解决方法:多刷群消息,通过别人讨论的问题,寻找有用信息,线下交流会,多跟老师交流,多尝试。
附上求路线的代码
1 | def process_10(car, road, cross): |