ACM学习路线

组队的事情我不多谈,我着重从个人的角度来说两句。主要分成两部分:
1. 理论部分
初学阶段要做的就是熟悉语言基础;熟悉基本数据结构和常见简单算法。
这些内容,书本里都有。推荐的书籍,《算法导论》。至于语言入门书太多了,不列举。
进阶阶段,看一下圈内的论文,学习进阶的算法和数据结构,比如变种的平衡树SBT;比如线性的素数筛法,中国剩余定理;比如dinic,预留推进,最高顶标;亦或者是快速的半平面交,凸包的交,高维凸包;又比如龙贝格积分,拉格朗日插值。
这里面有个重要的分类,就是动态规划。其实动态规划在学术界,我就用呵呵来形容好了。因为你根本就遇不到OI/ACM中那么复杂绕人的问题和模型,即使遇到了,直接建模,剩下的交给cplex就好。但是,在ACM界你会遇到很多很多的DP问题,变种,卡空间、卡时间,各种卡。所以得多看论文,培养解题的感觉是很重要的。
前一部分还是可以找到一些好看的书籍的,比如网络流,数论(初等数论、计算数论),数值分析,计算几何等。至于DP则没有啥好书了,作为一个刚上路的人,你会觉得理论和现实,差距真的好远好远。(但回过头来会发现其实理论真的描述了一切)
高级阶段,如果说初学阶段要做的是打基础,进阶阶段是加深深度,那么高级阶段就是加大广度。你需要涉猎许多理论,系统性的学习。比如你只知道dinic,只知道dijkstra,只知道bellman-ford是不行的,你需要知道整个图论它大概讲的是啥,你需要知道还有什么你是不懂的,不会的;再比如你只知道孙子定理,只知道丢番图方程是不行的,你需要系统地学习数论知识,你要深刻理解欧拉函数,要深刻理解莫比乌斯函数,要深刻理解扩展欧几里德,要深刻理解原根,等等等等。这样你才能知道原来扩展欧几里德可以轻松解出线性丢番图方程,你才能知道原来解二次丢番图方程要先解一下佩尔方程,你才能知道解高次同余方程就是质因数分解+扩展欧几里德+中国剩余定理。
在你涉猎了足够多的知识之后,再选择性的深入学习。为什么说是选择性的深入学习呢?因为一个人的精力始终有限,方方面面不能都照顾到,剩下的就要交给队友了,不然ACM为啥是个三人的比赛呢?
2. 实践部分
其实实践部分才是重中之重。
首先要知道ACM的代码是个什么样的水平。
1. 代码不多,大多在100行左右,多的在300行左右。当然,这些都是普遍的,也不排除有很长很长的代码。或者换种说法,大多数代码在1KBit左右,长的代码在3K,打表的代码不算。

2. 编程风格极“差”。这其中的代表有:
(1)几乎所有变量都是全局变量,因为平时练习中有内存限制,而静态变量区的大小足以应付。并且我们都知道,静态区的速度是要优于堆区的速度的,所以一般是不用new或者malloc的。
(2)代码怎么简单怎么写,以效率第一,牺牲部分代码可读性,牺牲安全性。
举个例子,比如用C++的选手,在没有特殊情况下,一般使用scanf而不用cin,这是因为前者效率比后者高许多,但scanf是有很多安全漏洞的,但是我们不管,因为我们正确的使用是不会导致问题的。
再举个例子,比如你用scanf读数据读到文件尾(EOF),一般的想法是用EOF != scanf(...)作为循环判断条件,而ACMer可能会写成~scanf(...)。总之,代码简写,效率第一。

3. ACM里的代码大多数是结构化编程,面向对象的绝对不用,基于对象的可以用一点。这是由于代码长度和效率优先的思想综合导致的。

好了,接下来是实践的正文。
ACM最重要的是什么,是 代码控制力。要做到写代码跟你讲话一样,不说错字(编译错误),不说错话(运行错误),表意正确(代码逻辑正确)。楼上说的做TC、CF的比赛当然是好的,但是这些并不适合初学者。



链接: 点击打开链接
首先可以说,在我认识的顶尖的 ACMer 中,很多人走的都不是在 OJ 盲目刷题的路。(当然也有特例,前提是他们的某方面基础或智商本身已经达到很高的水平。)不盲目刷题,我想原因也很简单,OJ 题目质量良莠不齐。对于大部分比赛套题来说,总会有防止人吃蛋的水题,也有故意刁难型的题目,有些赛区还流行论文题(结论题)、模板题,这些题目都不具备多少训练价值。而且,如果陷入了刷题量的虚荣漩涡,那会浪费很多时间。

有效地刷题只有两种情况:
  1. 刷套题。找比赛的感觉,给自己定位;
  2. 刷知识点专题。巩固基础。

除了刷题,更重要的一件事是做比赛。一般来说,建议常去 TopCoder Codeforces 比赛。这些地方题目质量有保障,大家的代码是公开的。同时很关键的是,这样的平台可以让你对题目的难度、比赛的进度、国内外顶级选手的实力做到心中有数,培养在大型比赛中所需要的大局观和节奏感。

另外,你可以尝试忘掉拿奖的事情。只要你真的有兴趣,拿奖是小 case,这个比赛还没到拼死拼活的地步。


作者:三鲜
链接: 点击打开链接
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

转自: 点击打开链接

1. 写解题报告

解题报告是为同学们的复习提供方便,就像课堂笔记一样。如果不写,有许多做过的题都会忘记,那做题对能力的提高就很小。因为目的是备忘,所以对于自己独立完成的题目可以简写。对于通过参考网上答案来完成的题目要细写。细写的解题报告要包含三部分:问题描述、解决办法、代码。详细程度要达到在自己完全忘记这道题的情况下通过解题报告能够了解题意和解题过程。写了解题报告还不算完,记得定期复习。

 

2. 写算法描述

做题的时候可能会接触到一些自己没学过的算法。在学习之后,需要用自己容易理解表达方式对算法进行描述,详细程度也是要让自己在完全忘记该算法的情况下能通过它迅速了解算法的原理或流程。同样记得定期复习。

 

3. 独立思考

做题可能遇到三种情况: 第一,独立思考就能完成,则略写解题报告。第二,需要上网找答案,但是并没有涉及到新算法,则详写解题报告。第三,需要上网找答案且涉及新算法,则详写解题报告,写算法总结。这三种情况中的后两种,即遇到不会做的题时,记得不要太急于上网找答案,先要充分地独立思考。这也是无数大牛强调的,对能力的提升有极大的帮助。但独立思考也要掌握分寸,思考时间过长会身心俱疲且浪费时间。

 

4. 查找答案

上述第三种情况可能直接看别人的解题报告并不能解决问题,因为解题报告通常只从算法的应用角度进行描述,并不描述算法本身。因此,要学习新算法还要上网搜索该算法的描述来进行学习,可以选择百度百科或者文库。

 

5. 写代码

写代码的过程中注意变量的命名,函数的抽象,如果时间不是十分紧迫的话,一定要保证程序结构清晰可读性强。因为整洁的代码可以大大提高DEBUG的效率。有些细节的处理可以参考网上别人的代码,学习一些细节处理的小技巧。尤其是第一次学习某个算法的时候,一定要阅读多种别人对该算法实现的代码,选择最适合自己作为以后自己的实现方法。

 

6. 整理模板

这个的难度要求就比较大,要求同学们做题后从自己的代码中提取那些可复用的部分(别的题也可以用的代码)保存成模板以后使用。先说明一下原因,现场赛可以带纸质资料,总结的模板是可以在比赛中用到的,可提高打代吗的速度和正确性。而别人总结的模板也可以用,但有时会出现用起来不顺手或者功能不全等问题。因此,总结自己的模板是必要的。为了复用性可以对代码做适当修改。注意添加注释说明,详细程度要达到在自己忘了这个模板的用法的情况下能通过说明了解其用法。

 

总体来说,初期的训练方法就是在OJ做题,通过做题来学习算法和提高各方面能力。当然有机会的要多在实战中锻炼自己。个人不建议单独看书学习算法,因为没有足够题目的强化,算法很容易忘记。




你可能感兴趣的:(ACM习题及反思)