最后一公里极速配送 - 阿里云算法大赛总结
简单回顾
从7月初开始参加了阿里云的算法大赛,第一赛季获得了第14名的成绩 ,第二赛季由于其他事情需要处理,获得了23名的成绩。对于一个没有受过专业算法训练,第一次参加算法比赛的我来说,成绩还是比较合理的。
经验总结
-
穷举部分应该最后加入
一般来说,算法题目总归缺少不了排列组合的尝试,但是如果过早的在算法中引入了排列组合的大规模计算,则每次代码运行时间会很长,非常浪费时间。这里可以有两个方案,第一,可以做一个系统配置项,是否启用排列组合的尝试;第二,可以将排列组合的强度也做成一个配置项。
所谓的排列组合的强度,就是算法的广度和深度的限制。例如背包问题,如果全部有10个元素,我进行全排列尝试,20个元素,则进行简单的贪婪算法。这里的10就可以认为是一个阈值,超过阈值的时候,考虑到时间成本,使用一般的算法。 -
保证每次运行结果都是符合题目要求的
在复杂的场景下,你的算法可能是非常优秀的,但是可能在一个很微小的点上,是不符合题目要求的。题目要求是最大的前提,如果违反题目要求,再好的算法都是不能被采纳的。所以务必检查每次的运行结果是否符合题目要求。 -
保证编码正确
有时候,一个想法是正确的,但是往往可能出现编码的错误,使得结果变坏。所以,必须保证你的代码和你的想法是一致的。如果出现你的想法使得你的运行结果变差的时候,不要先急着推翻你的想法,而是应该先看一下是不是你的代码有什么错误,没有真正反映出你的实际想法。 -
逻辑和阈值
在复杂的算法题目中,有时候我们喜欢用阈值来运行出不同结果,然后选择最优的结果。但是,如果可能的话,应该以统计等方式决定阈值。如果可能的话,应该有一个明确的逻辑,而不使用阈值。阈值没有泛用性,并且有时候由于不能测试每一个阈值的效果,容易出现局部最优解,而不是全局最优解 -
版本管理
不是每一个想法都会给结果带来正面的效果,有些改动可能不但没有效果,而且使得结果变坏,我们需要一个版本管理的概念,将不好的结果及时回滚到原来的状态。有时候,两个想法可能被同事加入到代码中,并且两个想法独立使用和一起使用效果也不同,这个时候更加需要版本管理工具了。建议使用Git做版本管理工具,可以自由的添加或者删减不同的想法。 -
自动测试 和 电源管理
这次没有准备自动测试的代码,正确的做法是,白天进行编码工作,晚上对于阈值,各种想法的排列组合的效果,进行自动测试。
在自动测试的时候,请注意电源管理的设定,需要看一下是否设定了休眠,如果设定了休眠状态,基本上什么都运行不了了。
对于每次自动测试的结果,都必须保留下来,作为算法的评价依据。 -
中间指标 和 数据分析
在最终目标之外,还需要订立一些其他指标来判断算法的好坏。
整个最终结果往往是由多种因素决定的,如果将这些因素的量化结果也打印出来,对于这些指标进行分析,往往可以找到优化点。
有一些题目,在写算法之前,可以将题目中给定的数据集进行一些分析,总结出数据集的特征,然后针对这些特征选择算法,也是一个很重要的步骤。 -
从答案中找问题
很多算法的最终结果可能是一些调度计划和分配方案。仔细观察这些结果,找到一些明显可以优化的点,这也是提高算法结果的途径。
从算法执行结果这个答案中寻找你的算法中存在的问题,是一条很有用的途径
算法和人生
算法比赛和人生有很多相识的地方,有一些算法在确定的时候,就决定了能够做出什么样的结果。
一个不好的算法,再怎么优化,得出的结果可能都比不上一个未经优化的好算法。当然,一个中庸的算法,虽然无法达到进过优化的好的算法的结果,但是往往可以接近一个未经优化的好的算法的结果。人生也是如此,选择比努力更重要。
引申开来,算法有时候也不能太转牛角尖,在一些小的局部细节上斤斤计较,而忽视了一些起决定性的因素。当然,这一点说起来容易做起来难。人人往往容易在微观的,局部的领域里面锱铢必究,而忘记从大局上找到问题的关键点。按照中心极限理论,有一些次要的因素,有些使得算法变好,有些使得算法变坏,但是这些因素的综合作用往往是相互抵消的。
编程语言
从算法层面来看,OOP的各种语言都是差不多的。很多人喜欢争论语言的优劣,其实如果真正研究算法和运筹学的,语言的优劣其实根本可以不用去考虑。使用你自己习惯的语言就可以了。我用C#习惯了,所以往往可以用C#的各种特性来简化代码,特别是Lambda和Linq这样的特性,熟练掌握的话,往往可以将负责的功能用简单的代码实现。如果真正静下心来,研究一些算法或者AI大数据的时候,你是根本没有时间和兴趣加入语言优劣的论战的。
C# 平台兼容性
注意:Windows平台的C#程序,在Mac上,用Mono执行出来的结果,可能是精度问题,结果会出现差异!有时候这些差异会影响结果。如果坚持要在两种平台上运行程序,请使用Java或者.NET Core
本文已经同步到 阿里云算法大赛总结