转眼之间,暑假一个月的时间就飞逝了。其实回过头来,你会发现时间过得真的很快,时间是抓不住的,关键是你如何利用时间,使有限的时间发挥最大的效率,提高时间的利用率。回过头,总结一下一个暑假的工作成果,其实也是一种收获。
首先,一进入假期我们就把精力投入到了DP上面,DP在ACM中非常重要的,同时又是竞赛中的难点,因为该算法时间效率高,代码量少,多元性很强,主要考察自己的思维能力和建模的抽象能力以及自己对知识点和题目的灵活度。动态规划背后的基本思想非常简单。大致上,若要解一个给定问题,我们需要解其不同部分(即子问题),再合并子问题的解以得出原问题的解。 通常许多子问题非常相似,为此动态规划法试图仅仅解决每个子问题一次,从而减少计算量: 一旦某个给定子问题的解已经算出,则将其记忆化存储,以便下次需要同一个子问题解之时直接查表。 这种做法在重复子问题的数目关于输入的规模呈指数增长时特别有用。其中动态规划问题满足三大重要的性质:即最优子结构性质、子问题重叠性质、无后效性,其中最重要的还是要找到状态转移方程,这一点是解决题目的核心和关键点。
其次就是搜索了。搜索是ACM中常用的算法,其中对于回溯算法,回溯算法是所有搜索算法中最为基本的一种算法,其采用了一种“走不通就掉头”思想作为其控制结构,其相当于采用了先根遍历的方法来构造解答树,可用于找解或所有解以及最优解。然后就是深度搜索与广度搜索。深度搜索与广度搜索的控制结构和产生系统很相似,唯一的区别在于对扩展节点选取上。由于其保留了所有的前继节点,所以在产生后继节点时可以去掉一部分重复的节点,从而提高了搜索效率。这两种算法每次都扩展一个节点的所有子节点,而不同的是,深度搜索下一次扩展的是本次扩展出来的子节点中的一个,而广度搜索扩展的则是本次扩展的节点的兄弟节点。在具体实现上为了提高效率,所以采用了不同的数据结构。搜索可以说是万能的算法,万能的模板,可能对于一些题目就是时间的问题了,虽说是万能模板,但是很容易就是超时。其中处理搜索问题的一些小技巧就是一些剪枝之类的了,这可以节省程序的时间,提高程序的运行效率。
再者就是二分算法了,二分算法具有很强的模板性吧,但是关键点还是要搞清楚变量的变化和二分的一些细节与内容。对于一些求最大值的最小值问题之类的,毫无疑问,就是运用二分的时候了,以求最小值的最大值(最小值最大化)为例,尝试一个可能的答案,如果这个答案符合题目条件,那么它肯定是“最小”(可行解),但不一定是“最大”(最优解),然后我们换个更大的可能答案,如果也符合条件,那这个新可行解就更优,不断重复即可。二分的前提是答案区间上下限确定,即最终答案在哪个范围是容易知道的、检验某值是否可行是个简单活,即给你个值,你能很容易的判断是不是符合题目要求、可行解满足区间单调性,即若x是可行解,则在答案区间内x+1(也可能是x-1)也可行。
然后就是我非常陌生的数据结构的内容了,先来说最小生成树,最常见的最小生成树,无非就两种:prim、kruscal。两者皆为贪心思想,局部最优(或无限接近最优)以达到全局最优的效果。
Prim算法简单描述:
1).输入:一个加权连通图,其中顶点集合为V,边集合为E;
2).初始化:Vnew = {x},其中x为集合V中的任一节点(起始点),Enew = {},为空;
3).重复下列操作,直到Vnew = V:a.在集合E中选取权值最小的边<u, v>,其中u为集合Vnew中的元素,而v不在Vnew集合当中,并且v∈V(如果存在有多条满足前述条件即具有相同权值的边,则可任意选取其中之一);b.将v加入集合Vnew中,将<u, v>边加入集合Enew中;
4).输出:使用集合Vnew和Enew来描述所得到的最小生成树。
Kruscal算法简单描述:
1).记Graph中有v个顶点,e个边
2).新建图Graphnew,Graphnew中拥有原图中相同的e个顶点,但没有边
3).将原图Graph中所有e个边按权值从小到大排序
4).循环:从权值最小的边开始遍历每条边 直至图Graph中所有的节点都在同一个连通分量if 这条边连接的两个节点于图Graphnew中不在同变量中, 添加这条边到图Graphnew中。
接下来我们再说最短路径,最短路径最常用的四种方法就是Dijkstra、Floyd、SPFA和Bellman-ford。
Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等。注意该算法要求图中不存在负权边。Floyd-Warshall算法(Floyd-Warshall algorithm)是解决任意两点间的最短路径的一种算法,可以正确处理有向图或负权的最短路径问题,同时也被用于计算有向图的传递闭包。Floyd-Warshall算法的时间复杂度为O(N3),空间复杂度为O(N2)。为了能够求解边上带有负值的单源最短路径问题,Bellman(贝尔曼,动态规划提出者)和Ford(福特)提出了从源点逐次绕过其他顶点,以缩短到达终点的最短路径长度的方法。 Bellman-ford算法是求含负权图的单源最短路径算法,效率很低,但代码很容易写。即进行不停地松弛,每次松弛把每条边都更新一下,若n-1次松弛后还能更新,则说明图中有负环,无法得出结果,否则就成功完成。Bellman-ford算法有一个小优化:每次松弛先设一个flag,初值为FALSE,若有边更新则赋值为TRUE,最终如果还是FALSE则直接成功退出。Bellman-ford算法浪费了许多时间做无必要的松弛,所以SPFA算法用队列进行了优化,效果十分显著,高效难以想象。SPFA还有SLF,LLL,滚动数组等优化。
然后就是我们现在正在进行的树状数组了。树状数组重点在于如何运用如何理解和如何运用他来简化问题,使得问题的复杂度降低,以便为我们解决问题提供便利。
假期结束,新的一个学期就要来临了,即使在教学周内,也不能放松对ACM的学习,不能前功尽弃白白浪费自己努力的一个暑假的成果,虽然自己水平目前还是很一般的,但是勤能补拙是良训。只有努力没有做不好的事情,人最怕认真两个字,只要认真起来,没有办不成的事情,没有迈不过的坎坷,新的学期,加油!!!