ACM学习心得

来源:互联网 发布:电池测试系统算法软件 编辑:程序博客网 时间:2024/06/03 22:40

转眼学习ACM已经将近一学期,首先我的ACM经历无法那些大神们相比,因为我是在进大学后才逐渐了解我的专业,才慢慢听说了ACM,也是在学习中发现自己挺喜欢自己学的东西。由于自己想在大学里学到更丰富的知识,让自己得到更充分的锻炼,让大学生活更有意义,加上自己对C++课程的信心,于是ACM激起了我的兴趣,上学期就想有机会一定要去参加。于是在后来参加了校内的新生程序设计大赛后,逐渐了解到可以在第二学期选修《ACM程序设计》这门课,虽然一开始有一些顾虑,但在经过一番考虑之后,我坚定了要学习它的决心,当然我也做好了为之付出时间和精力的准备。

学习ACM的过程对我来说真的是痛并快乐着,但这半年来却从未后悔过,也从未有过退却的想法,虽然我知道自己做的还不够好,但我一直在尽自己的努力用心去做,也盼望有一天自己真的能做好它。从第一节课开始,老师就跟我们说ACM课程就是给大家提供一个全身心投入去做好一件事情的平台。也是从那时候我端正了自己的学习的态度。而且从第一节课开始我也一直在珍惜这个学习的机会,希望自己能在短短12周里学的更扎实。虽然课程已经结束,但对我这个ACM新手来说这只是个开始,也许ACM的路以后还有很长要走。

从寒假里开始进行一些训练,从最开始的STL的学习,从对读英语题的适应,到后来难度慢慢提升,学到动态规划时ACM已经展示出它的难度,其实ACM就是一个高难度的东西,要求你高超的思维能力,但仅有这些还是不够,正是因为它的难度,所以这门课程就要求学习ACM的人必须有一定的积累才能出成绩,这对学习者是一个很大的考验。所以老师也在跟我们说虽然选课的同学不少,但是在经过一学期的学习和后面不断的训练,能真正坚持下来的人却不多,因为确实不是适合每一个人的。

ACM虽然困难,但我还是经常在做题过程中体会到快感的,比如一道题的代码一次性编译成功并一次性AC那种感觉还是难以忘怀的,有时候也会因为一道题有思路而又做不出来而痛苦,这时候时间流逝之快是惊人的,往往不知不觉几个小时就过去了。而让我对ACM的感情加深是因为参加省赛,从报名选拔赛到备赛这段时间还是很充实的。而且当时跟队友在一起赛前训练给我不一样的编程感觉,跟队友在一起编程确实比自己一个人编程效率高,我每次自己编程到后期就思维混乱,基本上就不会出题了,但跟队友在一起时通过交流能够保持较为清晰的思路,而且每个人一般都有自己的思路,但通过交流我能够发现自己思维的缺陷,也能学到队友在一些优秀方面的编程技巧,尤其是在调试代码过程中,大家在一起总能较快发现错误之处。而通过那段时间的训练,我也逐渐适应了三个人用一台电脑去写代码,而且因为备考还去学习到了一些知识点。包括在假期和运动会期间去本部学习、大家一起坐火车去青岛参加比赛,都是很棒的经历,是难以忘怀的。

ACM也并不是简单做题,在真正的ACM比赛中也是要讲很多策略的,包括队友的配合,做题时间的分配等等。还记得在省赛中我们根据老师的建议,我们组就明确的确定了比赛时开始并行,最后串行的策略,事实也证明这个策略是非常有效果的,我还记得我们在前三个多小时A了3道题,在封榜之前我们看到自己处于铜末,于是我们清楚我们一定要再A出一题才有机会拿奖,我们在商量之后决定最后对一道尝试过但没能够A的题进行猛攻,最终在结束前几十分钟,在出错了多次之后终于通过,那一刻我们的心情无比激动。在比赛之后我们经过总结也发现我们A的4个题和算法都没什么关系,也就是说我们的实力还有限,对于更难的题目还没有能力去解。而且通过省赛确实让我们增长更多的见识,也跟多的了解了ACM竞赛,因为我们没有比赛经验,而且初学ACM不久,所以对于这次比赛结果,我们都很满意,这是对于ACM新手的一个很好的鼓励。这次比赛也我们看到了我们的水平与其它高手之间的差距,所以我们也在心里认识到我们的ACM之路还有很长的要走。

总之,毫无疑问,在学习ACM的过程中收获非常多,而且在这个过程中对我的影响已经不只是学习到了多少知识,还有思维能力,合作意识,更重要的是,踏踏实实认真学习的态度,以及面对困难时的那份坚持,也让自己的大学生活有意义。然后学习ACM会对编程能力有很大的提高,而且它是要求你的代码完全正确而且还得要求速度和代码质量,这一点可能和其它编程过程不同。学习过程中你的算法的能力会得到很好的锻炼。因为在课堂知识里一般是不怎么涉及算法内容的,但是基本的算法学习还是必不可少的。扎实的算法和数学功底是计算机研究的必备条件,而这些正是ACM所培养的。而且ACM竞赛讲究三人组队配合,这点很符合现实中的团队合作,如何提高配合效率都是在ACM中可以学到的。而且能够代表学校外出去参加比赛,对于每位学生来说也是很激动很有意义的一件事。

在ACM的解题过程中讲究寻找最优的解法,一般在做题过程中会经常遇到这种情况:我们的代码已经能得出正确答案,但它可能仍然会被判TimeLimitExceeded或MemoryLimitExceeded,这就需要我们不断更换思路和方法,从不同角度分析问题,但其实这个过程也正是ACM魅力之所在,我觉得就算是以后其它方面编写程序也是如此,一个又费时间又费空间的代码就算是能运行又有什么意义呢。ACM让我认识到编程世界太庞大了,对于任意一个问题可能会有无数种解法,而且对于大部分程序它总是可以优化的,而且优化又是无止境的,这不正是我们所追求的吗。

ACM很重要的是对知识点的思考,对算法的思考,对思路的不断梳理,这在解题报告中会有很好的体现,所以对于一个好的题目写出它的解题报告也是提升水平的一个途径。ACM知识点的学习与其他学科那种简单的背背公式去应付考试还能考个好成绩的学习方法有本质区别,首先ACM很多知识时没有固定公式的,比如动态规划。对于一些有模板的知识点的运用那就得建立在理解的基础之上了,否则题目稍作变形就算你知道是哪个知识点你也根本无从下手。对于有的题目解决方式可能有多种,能否找到效率高的那个就看经验了。而且对于ACM题目,你的代码只有AC or notAC,在ACM竞赛中只要你AC不了那就是nothing,(当然还有罚时)。所以ACM的知识点你掌握不好是蒙混过关不了的。

然后我认为学习ACM需要以下几点条件:1、扎实的基础:STL、递归递推、动态规划、背包、二分、贪心、搜索、数据结构、图论算法、最短路径最小生成树算法、组合数学等等,这些是ACM要学的基础知识,如果不掌握它们,根本无法面对有些题目。2、丰富的想像力:要敢于大开脑洞,发散思维,不要拘泥于固定的思维方式,遇到问题的时候要多想几种解决问题的方案,试试别人从没想过的方法。就算对于能够A出的题目也尽量去其他方法试试,这个过程中的收获,将不再只是A出一道题目。丰富的想像力是建立在丰富的知识的基础上,除计算机以外,多涉猎其他的学科,比如物理、数学等等。开阔的思维对编程很重要。3、不钻牛角尖:我们容易陷入一种思维无法自拔,一直在一个错误的圈子里面来回的绕,尤其是自身水平不够时遇到不是自己能力范围内的题目时更是如此。所以当你遇到障碍的时候,不妨暂时远离电脑,看看窗外的风景,听听轻音乐,和朋友聊聊天。当遇到难题的时候可以去放松放松,让负责编程的那部分大脑细胞得到休息。当重新开始解题的时候,可能会发现那些难题现在竟然可以迎刃而解。4、对答案的渴求:人类自然科学的发展史就是一个渴求得到答案的过程,即使只能知道答案的一小部分也值得我们去付出。只要你坚定信念,一定要找到问题的答案,你才会付出精力去探索,即使最后没有得到答案,在过程中你也会学到很多东西。5、多与别人交流:三人行必有我师,也许在一次和别人不经意的谈话中,就可以迸出灵感的火花。听听别人对同一问题的看法,也许会给你很大的启发。6、韧性和毅力:这也许是大神和普通人真正区别所在。也许高手们并不都是天才,他们是在无数个日日夜夜中磨炼出来的。成功能给我们带来无比的喜悦,但过程也许是的枯燥乏味或者说是举步维艰的。就像有时候我们总会遇到一个自己难以攻克的问题,可能一下午或者一两天都出不了结果,而且这种情况是会经常有的,我们内否耐得住性子去解决这一个个的难题呢?而且有个说法:对于一个ACMer500道题目算是入门,想要做好得1000+题,有些大神做题已经2000+。所以想要取得成绩,那就看你能不能坚持下来了。

看过一篇关于新手怎么学ACM的文章,其中提到:对于新手来说,最重要的是能有稳定的代码能力和基本的解题能力,这得从两个方面入手,一方面,多刷一些练代码能力的题目,另一方面,多看书,看一些思维难度比较高的题目,尝试理清楚题目的思维以及细节。之后的训练从两方面入手,一是把自己脑子里面的那根筋打通,所谓那根筋其实就是:有的人想通了算法以后,十几分钟代码就打完了,而有的人想通算法以后,写代码的时候依旧磕磕绊绊,想一会这里,想一会那里,其实差的就是这根筋,因为这种思维这次想到了,但是并不熟练,所以写代码的时候还要不停的梳理,而且实现的时候可能在细节上也会不断调整。打通这根筋的主要办法是多写题,同一类的题目一直做,直到自己遇到下一道同类题目的时候,想出做法以后觉得AC对自己来说已经是小菜一碟的时候就可以不练这一类题目了。当你对一种题目信手拈来的时候,你就可以不再刷这一类题目了。这个训练过程需要很长的时间,但是是必须经历的一个过程,否则在比赛中,很难发挥出来。二是把自己的思维强度提升上来,在你实现代码已经完全没有问题的基础上,你就可以不再写代码玩了,而是转为看书or看题,想清楚算法以后对照题解,看自己想的是否正确,如果和题解一致or你确保你的算法的正确性,那么就可以跳过,如果不确定自己算法的正确性,可以打代码试一下。这个过程你将会在比较短的时间内积累大量的题目,从而提升自己的思维层次。时间分配上,做个总结吧,就是:前期以刷题为主,后期以看题为主,当然,模拟赛是必不可少的。

 

下面说一下对ACM知识点的总结:

第一类:基础算法 

(1)基础算法: C/C++、STL(vector、set、map、queue、string、algorithm)

枚举、贪心、递归、分治、递推、模拟、构造、位运算、常数优化;(2)动态规划:最长公共子序列、最长上升序列、背包九讲(0/1、完全、依赖、分组、泛化物品)、四边形不等式优化、斜率优化、单调队列(1D\1D)、数据结构优化(线段树优化、堆优化、左偏树优化)、树形DP、自动机DP、数位DP、状态压缩DP、插头DP、广义插头(最小表示);(3)搜索:dfs,bfs,记忆化搜索,优化与剪枝,双广,A*,IDA*,跳舞链。

第二类:数据结构 

(1)简单数据结构:链表,栈和队列,串,树和二叉树,图,排序与检索  (2) 树形结构:线段树,树状数组,字典树,伸展树,左偏树,动态树,lca&rmq,划分 树,SBT。(3)字符串:kmp,AC自动机,后缀数组,最小表示法。(4)其他:并查集,散列表,块状链表,双向链表。

第三类:图论 

(1)最短路:dijkstra,bellman-ford(spfa优化),floyd,heap+dijkstra ,差分约束,第K最 短路;(2)生成树:prim,kruskal, 度限制最小生成树, 最优比率生成树, 次小生成树, 最小树形图,生成树的计数,树的划分,树的枚举;(3)匹配问题:二分图的最大匹配 (匈牙利算法),KM,2-SAT,同构;(4)网络流:最大流,最小费用最大流,最小割模型、网络流规约;(5)其他:拓扑排序,双连通分量,强连通分支及其缩点,图的割边与割点,无向图、有向图的最小环,欧拉路径,哈密顿路径,平面图,分层图思想,偶图。

第四类:数学

(1)数论:素数和整除问题,进位制,同余模算术,整数因子分解,GCD,扩展欧几里得,求解模线性方程,中国余数定理,元素的幂,RSA公钥加密;(2)组合数学:加法和乘法原理,排列组合,递推关系和母函数,容斥原理,抽屉原理, 置换群与Polya定理,MoBius反演,偏序关系理论;(3)计算方法:二分法求解单调函数相关知识,三分法求解单峰(单谷)的极值,矩阵法,迭 代逼近,高斯消元法,随机化算法,0/1分数规划;(4)高精度问题扩展:求倒数,求乘幂,求开方,求对数,二分快速方法,对指函数,三角函数,数值计算的优化;(5)其他:博弈论,线性规划,整数规划,概率问题,多项式与快速傅里叶,数学思想与 方法的综合运用(构造,猜想,归纳法,反证法)。   

 第五类:计算几何

(1) 判断线段相交,判断直线相交,判断点是否在多边形内;(2)凸多边形面积&重心计算,求外接圆与内接圆;(3)求凸包,最近点对问题,最远点对问题;(4) 点集或图形集合的最小覆盖圆,点集或图形集合的最小覆盖矩形;(5) 矩形的交与并(扫描法);(6)三角剖分,费尔马点的计算,Pick定理;(7)常用几何公式。

对于这些知识点我现在了解的当然是少之又少,而且对于我个人,对各种学过的算法的掌握也是有很大差别的,尤其对数学、动态规划、背包、数据结构、图论算法、最短路径最小生成树算法、掌握还远远不够,在以后还得着重练习。

我是很期待参加暑假里的集训的,如果能够参加集训,我希望自己能够通过暑假里的集训更加了解ACM也更了解自己,进一步加深自己对ACM的感情。希望在暑假中在没有其它学业的压力下,通过全身心投入其中而找到不一样学习ACM的感觉。最后还是说句感谢吧,感谢经历,感谢我的一同参加比赛的两位队友,感谢老师,也感谢自己曾经的努力。

 

 

原创粉丝点击