有不少的朋友问过这个问题:在中学里面参加NOI,在大学参加ACM/ICPC,TopCoder,最后对实际工作究竟有多少用处?我把自己的一些理解总结了一下跟大家讨论。
我是在94~96年参加NOI和集训队,99~2000年参加ACM/ICPC,2002左右玩了半年TopCoder,后来就很少关注编程竞赛了,所以可能对近几年竞赛模式的变化不了解。另外我目前主要在工业界工作,所以“实际工作”主要指的是在IT工业界的技术型工作。
我想竞赛培养的能力可以分成几个类型:
1、基本技术技能。我想参加竞赛而且成绩不错的朋友,基本上都有三个非常出色而且难得的基本技术能力:算法设计、快速编程和自我调试。这是所有比赛都必须的: 给定一个问题,需要很快地设计出算法,很快地编写出程序,并且在整个算法设计和编程过程中不断拷问自己的设计和程序,尽早发现漏洞、完善设计,最后在提交结果之前通过一系列的测试尽量提高程序通过竞赛评委测试的概率。 这三项基本能力是工作里面非常有用的。 大部分公司的技术面试也集中在这三项基本技能里面。竞赛经验的确让优秀的参赛者在实际工作中获得先发优势,一般IOI/ICPC/TopCoder的优秀参赛者都很容易获得公司录取,并且在起始级别的工程师岗位上作得非常出色。
2、独立学习的能力和自信心。我想大部分的NOI参赛者都是中学就开始学习中学课程里面不函括的内容:面向对象程序设计、数据结构、图论和网络流理论、算法理论、离散数学等等。如果一个参赛者是通过自己独立学习这些课外知识而在竞赛里面脱颖而出的,她一定有独立学习的能力和自信心,同时相信自己能够很快的学会各种新知识。这个能力和自信在工作中非常重要:计算机语言日新月异,从Pascal/C到C++/Java到Python/PHP/Javascript/Objective-C⋯⋯一个人不可能从一开始就懂得所有的知识,但只要自信自己能学会任何新的语言和概念(并且的确可以学会),那他就可以敢于面对未知的挑战。在工作中,这些“敢吃螃蟹第一人”往往会得到更多机会去开发新项目、创建新公司。
3、表达能力。这一点我本人在吴文虎老师指导的NOI冬令营里面获益匪浅。当时吴老师要求每位冬令营选手挑选一个复杂的竞赛问题深入研究解法,最后写成论文,并且在冬令营里面做报告。吴老师亲自把关,指导论文里面写不清楚或者报告里面说不清楚的地方。这是我第一次学会如何把一个技术问题写清楚、说清楚。这样的训练虽然跟竞赛成绩本身没有直接的关系,但能够让竞赛选手的表达能力上了一个台阶。表达能力对实际工作有非常重要的意义:现代的大型软件系统开发不是一个英雄人物就能完成的,如果一个子系统的算法和程序不能清晰地被理解,那这个子系统和它的作者就成为单一故障点(Single Point Of Failure) —— 只要作者一度假,就没有人能维护或者扩展这部分。基于这种风险,大家宁愿用一个更慢更费内存但能被其他人看懂的解决方案。在这两年的招聘过程中,我看到不少这样的可惜例子:不少ACM/ICPC的选手能在15分钟之内写出一个很巧妙的算法,在机器上编译、测试例子都通过。 但在黑板上或程序注释里面,他们花20分钟也没能说清楚这个算法为什么是对的,为什么要用这个算法。
4、合作能力:NOI/IOI/TopCoder更多的是单枪匹马,而ACM/ICPC对合作能力的培养更有帮助。三个编程高手共用一台机器,紧缺资源谁先用谁后用,如何分工,这些问题在实际工作中每天都会遇到,如果一个选手在ICPC里面学会如何跟队友协调、如何培养信任,那她在实际工作里面就很容易融入一个团队,在团队里面找到自己的发力点 ,很快为团队作出贡献。
5、志同道合的朋友圈:一般来说,愿意花额外时间参加竞赛的学生都是喜欢写程序的,因为喜欢,他们往往更容易在这方面越做越好。我10年前在竞赛过程中认识的老对手,现在还有很多是好朋友,不时能联系一下,得到他们的指导、交换最新的行业信息和趋势。这一点虽然对实际工作没有直接帮助,但我觉得是参加竞赛获得的最宝贵的东西。
这些大概是我在比赛里面学到的最有用的一些东西。下次有时间的时候打算整理一下实际工作里面有哪些是竞赛里面学不到的。