前言
本帖是给本校大一生写的,致力于给有志于搞ACM-ICPC的同学一个了解概况的机会,是基本的入门扫盲帖子。诣在给出一个大局观,给出一个可以努力的方向。以下纯属个人见解,若有谬误,敬请指出。
关于ACM
ACM是一项非常难的竞赛,需要大量的训练时间,需要强大的抗压能力,需要良好的团队配合,需要足够的天赋。以上四点除了最后一点以外都是可以用足量的时间来换取的,天赋可以让你在天才之间的撕逼中脱颖而出,但大多数acmer都是大一开始接触编程的,因而所能达到的高度主要取决于个人与团队的努力。
ACM赛场上的目的是在尽量短的时间内过掉尽量多的题目。acmer需要关注的问题,一是怎么写可以过,二是怎么写最容易过,三是怎么写能在最短时间内过。具体来说,一是要学习或找到可以解决问题的算法,二是要选择比较好的解决方式或者将问题转化为较为容易解决的问题,三是找到一种代码量,调试量较小的实现方法。
基础入门
要搞acm最相关的基础课程是《C/C++》《数据结构》《离散数学》。《C/C++》由于其性能优势,是编程竞赛的主流语言,Java Pascal次之,Python属于后起之秀,正式的比赛一般支持C/C++/Java。《数据结构》《离散数学》是最基础的知识需要掌握稳固。
关于入门的书籍学习语言我推荐《C++ Primer Plus》,C的话我不清楚,但我觉得《C Primer Plus》应该也是不错的选择。C/C++的基本写法是C输入输出的C++或者纯C。《数据结构》一般的教科书即可,差别不太大。《离散数学》可以选择Roson第七版的,机械工业的,已经有中文的了。
竞赛的入门书籍比较推荐《挑战程序设计竞赛》或者刘汝佳的《入门经典》,不推荐买本《算法导论》防身。
著名线上比赛网站(均为提交代码开源):
成为一位强大的acmer
成为一位强大的acmer一是要看个人的实力,二要看团队的实力。
个人的实力可以通过写题,读书,读论文,读blog,打比赛来提高。主要的衡量标准一是看题量,二是看网上竞赛的rating,三是实际的比赛能力。
ACM是团体比赛,团队能力更为重要(除非队内有一人七题的杜教主)。团队的实力可以通过组队训练,提升个人能力来提高,最好的做法是任何团体赛都是单机操作,真实模拟比赛环境,这个是SJTU真实的做法。团队能力并非简单进行max或者加和的操作,存在大量队伍能够以较低的相对rating战胜rating相对高的,当然差距较大时基本不可能,合作以弱胜强的基础是一定的个人实力。对于一个团队而言最重要的是要用完整的技能树以及相互协助的能力,可以在初期就分配好每个人主要攻克的方向,之后可以逐渐加深各个方向的覆盖,最好保证每人会一些基础的算法,然后一个人的题其他人可以帮忙进行调试或者提供思路。
有种说法说是选对赛区少奋斗一年,选对队友少奋斗一辈子。选赛区很重要,赛场上万事皆有可能发生,赛区拿牌或者出线难度也各不相同,赛区这个东西要看团队的技能树还有对手的能力,这个需要经验以及强大的运气支撑,在此不多进行讨论。选队友这个事情很重要,具体的标准,一要看基础实力,二要看进步速度,三要看人品,四要看脸。前俩其实就是看能力,存在不少人可以一年超神,看出大神潜质就可以直接死死抱住大腿,共同进步。人品就是看对不对眼,存在一些人有一定水平但是处事让人不舒服或者行为不好,因为要长期一起训练,要慎重(当然大多数acmer都是正直,可爱,善良的宅男女)。假如你是萌妹子(萌汉子),找到一个强大的汉纸(妹纸)作为朋友(各种朋友),就可以被稳定带飞了,有脸可以选择男女通吃,兼容并包,走向人生巅峰。
中国属于ACM的强国,按照cf中的rating通常而言三个低分小蓝能打个铜,三个高分的小蓝或者低分小紫可以打个银,三个高分小紫或者低分橙名可以冲金,比较强的橙名或者是红名组队基本可以金牌冲出线,再向上基本就可以冲wf奖牌了。以上只是经验结论,存在一些人rating较低但赛场上很强,也存在rating较高的人赛场上不行。
个人实力的提升
个人觉得个人实力主要是看编码能力和算法能力。
编码能力:
- 熟悉各类语言,掌握C/C++/Java的基本运用(库函数)
- 熟悉各种优化技巧,各种预处理,乱搞的方法,熟悉调试
- 良好的命名风格,代码风格,了解设计模式,面向对象
衡量的主要标准大概就是实现算法的速度,写模拟题的能力,还有对于卡常数题目的处理能力,训练方式就是多写题目,多看资料。另外一个方法看你的队友是否能够很舒服地调试你的代码。风格我认为比较重要,因为acmer大多缺乏对于良好风格的追求,而写出漂亮的代码对于调试而言很重要,也能让人理清逻辑。可以参照各类软工书籍如《代码大全2》,《Head First Design Pattern》,可以取其中和编码时间不冲突或者效益大过浪费的时间的。
算法能力:
- 掌握的算法及知识的量,即广度,涉猎面较广可以从多方面看问题,更容易解决问题。
- 掌握的深度,即做难题的能力,一些题目在思维上突破比算法本身重要。
- 数学能力,让你能更好地分析问题,找到问题的关键或是直接利用公式获得答案。
- 脑洞,让你能够更好地改造,组合,运用算法,让你突破传统算法禁锢。
acm入了门之后大量的时间都是在学习数学。几乎所有的计算机理论均是基于数学的,算法大师也多是数学家,算法论文里也都是数学符号。要想搞好acm学习各种数学是不可避免的。当然计算机学科的数学和数学系的数学又有不同,一切都是要计算机容易算,但思路基本是同源的。擅长数学或者搞过数学竞赛的人搞起acm也是如鱼得水(如rng_58,quailty)。
ACM的大方向
- 乱搞(哈希,小模拟,预处理,贪心,枚举,搜索),通常较易,也有难题
- dp,难易度变化大,脑洞
- 图论,较难,常有银牌金牌题
- 数据结构,难易度变化大,模板好用
- 计算几何,常有几何压轴题,代码量长
- 字符串,常常有对应数据结构,有色牌
- 数论,组合,概率论各类数学,常常融入题目中,单独出现则不是很难就是很简单。
- 大模拟,通常为银牌之后,强队才会练
以上为基本的大方向,但可怕的是常常出现算法的组合,dp,数据机构,数学常常与其他知识组合出现。许多问题可以转化为图论解决。另外很多偏门,奇怪的知识都能在ACM得到运用。
dp,乱搞,模拟之外的基本都是能够建立模板的,挑选常用的算法封装为好用的模板可以大大增快写题的速度。
个人认为初期的时候可以多训练一些简单的题把握好基本的语言。之后可以找本书入门,再由图论或者dp入手开始掌握一些算法题,因为这两个方向题量充足,ACM中出现频率也高,各个档次的题目都有。然后其他方向的简单算法也可掌握,待到基本没有特别短板可以找自己喜欢的方向深入挖掘。
读物推荐
- 《代码大全2》可以了解下其中对于代码风格的阐述,写好看代码是件好书。
- 《挑战程序设计竞赛》入门书籍,代码优美,翻译清晰,好书!可作模板,有语言基础去读。
- 《算法导论》有志于科研或者了解算法背后机理的推荐,不推荐用作入门或者带去赛场,题好。
- 刘汝佳系列,入门经典适合无语言基础的,有基础可略过部分,训练指南可用作提高。
- 《具体数学》各类计算机数学,题好,可用于数学进阶。
- 余勇系列,哈工大系列,均为套书,强大的模板套装,也可用作学习,进阶用。
- 各类数学去学习教材即可,《运筹学》《概率论》《计算几何》《初等数论》
- 各路大牛的代码/博客,挑风格好,代码清晰的,条理清晰的。如ACdreamer 叉姐(ftisach) TankEngineer Petr!