ACM总结报告

                                                                                             ACM总结报告

                从上个学期选课时的犹豫,到经过一个学期的学习开始写总结报告,回想起来,感觉还是很庆幸当时选了这门课的。虽然这个学期我学的并不好,各个专题的提交量也不是很多,甚至于好多题还是看的题解,但我感觉经过一个学期的练习以后,我的代码水平跟以前相比有了很大的提高,做题时的思维方面要比以前严谨了许多。

  通过学习ACM,我第一次认识到计算机功能的实现不仅仅是简单的场景模拟,用更通用更简练的算法能让事情事半功倍,在大数据处理上也第一次认识到了算法的优越性。可以说在大一就开始接触算法让我对编程有了一个新的认识,如果没有选这门课的话,或许我到现在还只会用简单的模拟去做题。虽然这个学期磕磕绊绊的过来了,自己也有了一些收获,但是感觉这个学期过的并不怎么样。因为自己思维逻辑不够严谨的原因,自己做题很少有一次AC的时候,更多的是自己写半个小时的代码因为不断WR然后去调试,一两个小时过一道题对我来说是很正常的,一点效率都没有。当然,到后来动态规划深搜广搜的时候看到题目一点头绪都没有去找题解的次数也不在少数。那时候我感觉自己是痛苦的,一道题目,看完题解以后突然发现原来可以这样做,原来这个知识点可以这样用,好像看起来并不难,但是自己就是想不到。但是感觉自己在一次次的看题解敲代码的过程中对代码的理解还有整体布局提高了不少,至少上个学期我还是个连个杨辉三角都写不出来的渣渣,这个学期已经可以对老师布置的作业很快的完成了。

其实仔细想一下,这个学期因为ACM的原因,可能会成为我大学四年的一个重要转折点,或许我进不了ACM队,甚至于暑假的集训我也参加不了,但是它已经让我认识到了很多,让我知道计算机没有那么简单,计算机更新换代很快,计算机要学的东西有很多,计算机是思维和能力的结合。安于现在课本上学到的那一点点是不够的,是需要自己不断努去丰富和提高自己的,否则,大学四年后,当别人面对着面试官的问题侃侃而谈的时候,自己支支吾吾很不好意思的说不会的时候甚至连笔试都过不了的时候,可能那时候回首大学生活,自己会后悔不已。不管怎样,至少在这个学期以后,我知道了自己课余的时间是不能荒废的,变则通,通则能够走的比别人远,大学里不能再依靠老师,要靠自己,路是自己走出来的。

这个学期,虽然感到自己有些许进步,但学长说我还没有入门,的确,那么慢的效率确实不能算是入门。但是感觉自己也学到了不少,虽然应用能力差了点,但是理论知识好歹也能会一点嘛。这个学期首先学的STL模板,感觉学完以后写代码真的方便了许多,例如字典树那个题目,我还清楚的记得当时没有想到用map来做,自己写了个模拟,好像有一百多行,不过到最后还是因为有一些问题也没有通过,后来知道了map,将元素插入到map(红黑树)中的时候,map会根据设定的比较函数将该元素放到相应的节点上去。在定义map的时候如果没有指定比较函数,那采用默认的比较函数,即按键值由小到大的顺序插入元素。用map很方便的就写出来了,不到三十行就AC了。

还有sort排序,再也不用自己一遍遍的写冒泡选择排序了,而且效率还高很多。个人感觉用的比较多的就是mapset,sort,队列和栈,特别是队列,在后来的广搜里面寻找最短路径特别好用。不过那本ACM程序设计我没有看完,当时没有意识到重要性,做的题也不多,到后期还是要用到的,慢慢补上了。

再后来学的就是递归递推了,一个含直接或间接调用本函数语句的函数被称之为递归函数,它必须满足以下两个条件:

1) 在每一次调用自己时,必须是(在某种意义上)更接近于解;

2) 必须有一个终止处理或计算的准则。

程序直接或间接调用自身的编程技巧称为递归算法(Recursion)。

它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解。感觉递归函数是后来几个专题的基础,特别是动态规划深搜广搜,都离不开递归函数,递归函数是用时间来换取空间,虽然增加了程序的可读性,但是也降低了程序的执行效率。

递归的基本思想:把一个不能或不好解决的大问题转化为一个或几个小问题,再把这些小问题进一步分解成更小的小问题,最小问题可以直接解决。感觉这个思想跟数学上的微积分挺像的,同样是把一个问题不断分解,然后求出答案 。但是递归还是有区别的,递归的关键在于找出递归定义和递归终止条件。数学只需要无限分解即可。递归专题给我印象最深的是那个全排列问题,乍一看要找出所有的排列组合,感觉很不好做,但是用递归几行代码就出来了,而且也很好理解。至于递归,定义是一个问题的求解需一系列的计算,在已知条件和所求问题之间总存在着某种相互联系的关系;如果可以找到前后过程之间的数量关系,能使复杂运算化为若干步重复的简单运算,充分发挥出计算机擅长于重复处理的特点。

递推算法的首要问题是得到相邻的数据项间的关系(即递推关系)。把一个复杂的问题的求解,分解成了连续的若干步简单运算。

这个专题给我理解最深的是那个上楼梯问题,就是一次可以上一个或两个台阶,问总共有多少中走法,每一个台阶只有两种情况,由它的前一阶走了一步,或者由它的前两阶走了两步,然后一次递推,只需要知道刚开始第一阶和第二阶的状态就能一次递推出后面到达每个台阶的方法。这道题浅显易懂,让我很容易的理解了递推的含义。记得当时做题的时候感觉就是找数学规律,于是做题的时候就是通过几个数据来寻找它们之间的联系,到后来才发现自己的思路是错的,还没有真正理解递推的含义,可以说那道题给了我很大的启发,也是第一次让我认识到分析问题不要总是从数学的角度去想,换一种思路,也许同样的过程,但是想出来要容易的多,只要找到了问题中的子问题,就可以解决整个问题。

然后就是动态规划专题了,不得不说,这个专题确实很难,在学这个专题的时候我感到很吃力,我甚至想放弃来,这个专题的例题我也没有看几道,专题也就做了几道并且几乎每道题我都搜过题解。现在回想起来,动态规划问题就是在多阶段决策问题:如果一类问题的求解过程可以分为若干个互相联系的阶段,在每一个阶段都需作出决策,并影响到下一个阶段的决策。

多阶段决策问题,就是要在可以选择的那些策略中间,选取一个最优策略,使在预定的标准下达到最好的效果.在多决策问题中选取最优解,不论初始状态和第一步决策是什么,余下的决策相对于前一次决策所产生的新状态,构成一个最优决策序列。最优决策序列的子序列,一定是局部最优决策子序列。包含有非局部最优的决策子序列,一定不是最优决策序列。这里有一个指导思想,在做每一步决策时,列出各种可能的局部解,依据某种判定条件,舍弃那些肯定不能得到最优解的局部解。

以每一步都是最优的来保证全局是最优的。换句话说,按我的理解就是在递归的每一层中选取一个最好的下一个递归,确定好每一个状态的对应的下一个最好的状态,不断前进,到最后得到最优解。把递归的框架想好了,然后就是下一个状态的确定,这些都好了应该差不多了(这只是我一个渣渣的理解,不足之处还请老师见谅)。当然,说的容易,真正做起来还是很有难度的,对问题的分析不到位,当时对这个专题也是一知半解的,好像真没有自己独立做出来一道题。仅有的几道题还是跟课件上一样的题,看了以后自己敲出来提交通过的时候感觉也就那么回事,不过自己做就不是那么回事了。记得当时自己在网上还特意找到了一个动态专题的博客,上面好多题题解,本来打算自己有空多看看的,但好像自从那个专题过去了以后就再也没有看过,无论如何这个暑假也是要看看的,这次不能只是打算打算了,至少要把以前没有搞明白的弄明白,不会做的题再弄一遍。

当然的确如老师所说,动态规划是最难的一个专题,以后就简单了。

接下来的二分好像是很容易理解的,就是折半查找,通过上下界的界定来确定元素。好像这个算法在 笔试当中很容易找到。二分查找的定义是简单定义:在一个单调有序的集合中查找元素,每次将集合分为左右两部分,判断解在哪个部分中并调整集合上下界,重复直到找到目标元素。

它时间复杂度:O (logn),优于直接顺序查找O(n),相比顺序查找确实快了不少。二分法不止可以用来查找一个元素的位置,还可以拓展出别的应用,对于某些问题,如果答案具有特定的范围,并且验证答案是否成立的函数具有单调性。则可以在范围内对答案进行二分验证,从而快速确定答案。只要问题具有单调性,应用二分法是很方便的,但是自己在做这个专题的时候也总是出错,到后来才知道精度卡的不够。感觉这个专题的题目,因为是 一个专题,上来就知道要用二分法去解决问题,所以在没有思路的情况下也尽量往二分靠,我觉得要是把各个专题混起来做的话,再做二分的题目我可能想不到要用二分去解决这个问题,还是自己总结的不够,这个暑假无论如何要把这个学期学过的再捋一遍,好多地方不明不白的,温故而知新嘛。

然后就是贪心专题了,贪心,顾名思义就是很贪,所以每次都要最好的,所以在问题的每一步都要选择最好的,所有的最好的就组成了整个问题的最好的答案。在求最优解问题的过程中,依据某种贪心标准,从问题的初始状态出发,直接去求每一步的最优解,通过若干次的贪心选择,最终得出整个问题的最优解,这种求解方法就是贪心算法。

从贪心算法的定义可以看出,贪心算法不是从整体上考虑问题,它所做出的选择只是在某种意义上的局部最优解,而由问题自身的特性决定了该题运用贪心算法可以得到最优解。

如果一个问题可以同时用几种方法解决,贪心算法应该是最好的选择之一。理论基础,贪心算法是一种在每一步选择中都采取在当前状态下最好或最优的选择,希望得到结果是最好或最优的算法。

贪心算法是一种能够得到某种度量意义下的最优解的分级处理方法,通过一系列的选择得到一个问题的解,而它所做的每一次选择都是当前状态下某种意义的最好选择。即希望通过问题的局部最优解求出整个问题的最优解。

这种策略是一种很简洁的方法,对许多问题它能产生整体最优解,但不能保证总是有效,因为它不是对所有问题都能得到整体最优解。

利用贪心策略解题,需要解决两个问题:

1)该题是否适合于用贪心策略求解;

2)如何选择贪心标准,以得到问题的最优/较优解。

这个专题感觉是动态规划的改进版,最让人头疼的背包又出现了,我记得这个专题我的提交量应该是最少的一次,感觉就是好难做,自己想不出来,又不想照着人家的题解打,就这样过去了。

搜索专题感觉挺有意思的,也只有在这个专题我把所有的例题都看了一遍,感觉挺好理解的。搜索算法是利用计算机的高性能来有目的地穷举一个问题的部分或所有的可能情况,从而求出问题的解的一种方法。

相比于单纯的枚举算法有了一定的方向性和目标性。算法是在解的空间里,从一个状态转移(按照要求拓展)到其他状态,这样进行下去,将解的空间中的状态遍历,找到答案(目标的状态)。广搜一般用来解决类似于最短路径问题,队列在这里面很好用,把每一个状态一次入队,从对头开始遍历,最先到达目的地的那个元素就是要找的答案。

深搜则是用的栈,1每次取出栈顶元素,对其进行拓展。2、若栈顶元素无法继续拓展,则将其从栈中弹出。继续1过程。3、不断重复直到获得目标状态(取得可行解)或栈为空(无解)。只要题目理解了代码实现就很容易了感觉,不断地递归调用,不过要用一个数组来标记每一点是否走过,在搜索以后还要修改回原来的状态便于下一次的搜索。

至于后面的数据结构,树和二叉树,自己也只是在上课听了听,图论算法,也第一次让我看到了把图形问题用代码表达出来并解决,感觉真的很厉害。

总的来说,这个学期的ACM学习,让我学到了很多,不只是知识方面的,更重要的是思维和代码能力。通过学习,我感觉到在考虑问题时不只是单纯的从数学的角度去找规律,也开始渐渐的不去想暴力打表的方法去做题,会开始分析问题,把问题分解,尽力去寻找更好的解决方法。也是在这个学期,我看了好多题解,了解到了好多解题套路,让我知道原来这个知识点原来还可以这样用,这个问题还可以从这个角度来考虑。当然,代码能力相比以前也是进步了许多,以前一个小代码都要出好几个错误,现在基本上可以一遍过。一个学长说,算法是可以决定一个人的上升高度,我觉得很有道理,以后想要走的更远,算法是很重要的,这个学期结束了以后不管怎样我也不会放弃算法的学习的,可能学的慢,但是不能停。现在回想起当初劝我不要选这门课的人,我想,如果他们真的选了这门课的话,也许会改变他们的看法吧。

 

 

 

你可能感兴趣的:(作业)