2017/8/25 训练总结(最终版QAQ)

来源:互联网 发布:阿里云解析的别名在哪 编辑:程序博客网 时间:2024/05/29 21:29

虽然说不上时光飞逝,但是暑假集训确实很快就过去了。

这次暑假集训从7月31日到现在,每天从早上八点到晚上八九点钟都待在实验室,坐在电脑前,开始不停的看题,码代码,学习新的知识,总结,写训练日记。说实话过的很累,但也很充实很开心。但我觉得这就够了,能够有兴趣的学习一门自己想学的知识,比被强制灌输一些根本用不到的知识要强很多而且学习的效率也会有很大的不同。

还记得刚开始接触acm的时候,大概是在大一上学期末,真正的开始深入的学习的话就到了下学期选修了费老师的acm程序设计,这也是我们这一届大多数人所面临的困境,因为要想在大一下学期到大三这短短的两年里,想要成为一名优秀的acmer,这根本就是一件不可能的事情,但是费老师对我们的期望是,在大学期间能够拼尽全力去做一件事,而事实上acm也是值得我们去为之努力的。

算法和数据结构是程序的灵魂。在我每次浏览csdn网站时都会出现这句话。而acm就是对算法和数据结构的使用。

开始的时候去做acm的练习题,就是去做水题,也不单单的只是水题,而是去做那些不涉及到算法却需要去思考的思维题,去训练自己的编程能力,适应下acm编程的节奏。

再到后来,学习了基础的算法之后就开始去做那些简单的算法题了。

最开始接触的算法或者说是思想的话就是递归和递推,菲波那切数列嘛。

再到后来就是贪心算法,搜索,动态规划以及图论和数据结构部分了。

所谓贪心算法是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,它所做出的仅是在某种意义上的局部最优解。

贪心算法没有固定的算法框架,算法设计的关键是贪心策略的选择。必须注意的是,贪心算法不是对所有问题都能得到整体最优解,选择的贪心策略必须具备无后效性,即某个状态以后的过程不会影响以前的状态,只与当前状态有关。

所以对所采用的贪心策略一定要仔细分析其是否满足无后效性。

基本思路:

1.建立数学模型来描述问题。

2.把求解的问题分成若干个子问题。

3.对每一子问题求解,得到子问题的局部最优解。

4.把子问题的解局部最优解合成原来解问题的一个解。

贪心策略适用的前提是:局部最优策略能导致产生全局最优解。

而且考查贪心算法的时候它往往也不是单独出现的,而是结合其他算法同时考查。

搜索,搜索又分为bfs和dfs(广度优先搜索和深度优先搜索)。

广度优先搜索(BFS)基本思想:从初始状态S 开始,利用规则,生成所有可能的状态。构成的下一层节点,检查是否出现目标状态G,若未出现,就对该层所有状态节点,分别顺序利用规则。生成再下一层的所有状态节点,对这一层的所有状态节点检查是否出现G,若未出现,继续按上面思想生成再下一层的所有状态节点,这样一层一层往下展开。直到出现目标状态为止。

深度优先搜索(DFS)基本思想:从初始状态,利用规则生成搜索树下一层任一个结点,检查是否出现目标状态,若未出现,以此状态利用规则生成再下一层任一个结点,再检查,重复过程一直到叶节点(即不能再生成新状态节点),当它仍不是目标状态时,回溯到上一层结果,取另一可能扩展搜索的分支。采用相同办法一直进行下去,直到找到目标状态为止。

而在搜索里面经常会出现timelimit error这种情况因此就需要剪枝优化或者更改代码,因此用到二分、三分查找的次数很多。

二分查找是指在一个单调有序的集合中查找元素,每次将集合分为左右两部分,判断解在哪个部分中并调整集合上下界,重复直到找到目标元素。对于某些问题,如果答案具有特定的范围,并且验证答案是否成立的函数具有单调性。则可以在范围内对答案进行二分验证,从而快速确定答案。对于求解一些实际问题,当公式难以推导出来时,二分、三分法可以较为精确地求解出一些临界值,且效率也是令人满意的。

BFS用的是队列,DFS用的是递归。递归之前就会用,所以深搜学起来用起来很快,但是队列则是在熟悉STL的有过接触。

广搜是求解最优解的一种较好的方法,而深搜一般会用于只要求求解,并且解答树中的重复结点较多且重复较难判断时使用。

当然,还有双向广搜。单向广搜虽然可以得到最优解,但是空间消耗增长快,如用双向广搜,则在理论上可以减少二分之一的搜索量,可有效提高搜索速度。

对于我们这个初学者来说重难点其实是动态规划,当时理解起来困难但真的理解清楚了做题的时候思路还是很清晰的。动态规划常用来解决多决策问题。

而所谓的多阶段决策问题是指:如果一类问题的求解过程可以分为若干个互相联系的阶段,在每一个阶段都需作出决策,并影响到下一个阶段的决策。多阶段决策问题,就是要在可以选择的那些策略中间,选取一个最优策略,使在预定的标准下达到最好的效果.

最优性原理:不论初始状态和第一步决策是什么,余下的决策相对于前一次决策所产生的新状态,构成一个最优决策序列。最优决策序列的子序列,一定是局部最优决策子序列。包含有非局部最优的决策子序列,一定不是最优决策序列。

动态规划问题具有以下基本特征:问题具有多阶段决策的特征。每一阶段都有相应的“状态”与之对应,描述状态的量称为“状态变量”。每一阶段都面临一个决策,选择不同的决策将会导致下一阶段不同的状态。每一阶段的最优解问题可以递归地归结为下一阶段各个可能状态的最优解问题,各子问题与原问题具有完全相同的结构。

动态规划的几个概念:

阶段:据空间顺序或时间顺序对问题的求解划分阶段。

状态:描述事物的性质,不同事物有不同的性质,因而用不同的状态来刻画。对问题的求解状态的描述是分阶段的。

决策:根据题意要求,对每个阶段所做出的某种选择性操作。状态转移方程:用数学公式描述与阶段相关的状态间的演变规律。

动态规划问题的一般解题步骤:

1、判断问题是否具有最优子结构性质,若不具备则不能用动态规划。

2、把问题分成若干个子问题(分阶段)。

3、建立状态转移方程(递推公式)。

4、找出边界条件。

5、将已知边界值带入方程。

6、递推求解。

最后动态规划可以简单地总结为:

动态规划算法通常用于求解具有某种最优性质的问题.在这类问题中,可能会有许多可行解.每一个解都对应于一个值,我们希望找到具有最优值的解

动态规划的基本思想其实就是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的。

使用动态规划时的一般步骤为:

1、找出最优解的性质;

2、递归地定义最优值(写出动态规划方程);

3、以自底向上的方式计算出最优值;

4、根据计算最优值时得到的信息,构造一个最优解。

对于最优化的问题,搜索可以说是万能的。所以动态规划可以解决的问题,搜索也一定可以解决。把一个动态规划算法改写成搜索是非常方便的,状态转移方程、规划方程以及边界条件都可以直接“移植”,所不同的只是求解顺序。动态规划是自底向上的递推求解,而深度搜索则是自顶向下的递归求解。

图论算法部分我们只是接触了比较基础的像求最短路径和最小生成树,但像网络流、拓扑排序之类的我们还没有接触到。但上次做题的时候有涉及到一个拓扑排序的题,真的是边学边写代码。图论算法是我们经常用来求解实际问题的一种方法在数学建模的求解过程中也经常应用。

生成树的概念:联通图G的一个子图如果是一棵包含G的所有顶点的树,则该子图称为G的生成树。生成树

 

带权图分为有向和无向,无向图的最短路径又叫做最小生成树,有prime算法和kruskal算法;有向图的最短路径算法有dijkstra算法和floyd算法。

prime算法的基本思想:

1.清空生成树,任取一个顶点加入生成树

2.在那些一个端点在生成树,另一个端点不在生成树里的边中,取一条权最小的边,将它和另一个端点加进生成树

3.重复步骤2,直到所有的顶点都进入了生成树为止,此时的生成树就是最小生成树。

Kruskal算法:构造一个只含n个顶点,而边集为空的子图,若将该子图中各个顶点看成是各棵树的根节点,则它是一个含有n棵树的森林 。之后,从网的边集中选取一条权值最小的边,若该边的两个顶点分属不同的树 ,则将其加入子图,也就是这两个顶点分别所在的 两棵树合成一棵树;反之,若该边的两个顶点已落在同一棵树上,则不可取,而应该取下一条权值最小的边再试之。依次类推,直至森林只有一棵树。kruskal算法能够在并查集的基础很快的实现。

Floyd算法是最简单的最短路径算法,可以计算图中任意两点的最短路径。如果是一个没有边权的图,把相连的两点  间的距离设为dist[i][j] =1,不相连的两点设为无穷大,用 floyd算法可以判断i,j两点是否有路径相连。

而dijkstra算法用来计算从一个点到其余所有点的最短路径。

 

数据结构部分目前接触的除了简单的栈,队列,单调栈和单调队列之后,又开始学习树状数组和线段树,对线段树的学习可能要拖到开学后一周。

 

树状数组非常的巧妙,能大大提高效率,难点就是不好往这个方向想。主要解决单点更新和区间查询或者区间更新和单点查询还有就是求逆序列对。

能用树状数组解决的问题,都可以用线段树来解决,反之则不一定。

另外就是树状数组有很多都是模板题,到时候可以直接套用模板来做题。

关于这次暑假集训的要求:

核心原则:知其然,更知其所以然;刷题是手段,提升实力才是根本目的。
对于知识,要明白:它是解决那方面问题的,其核心思想是什么;具体的实现原理是什么、用了那些技巧?可以出什么样的题目?
对于题解,搞清楚:主要考察什么、包括了那些基本问题又如何串联在一起的?题目有那些坑?如何找出解题思路的?你能出几道类似的题目吗?那就出几道难为一下队友!
对于题目,要做到:思考后,有了清晰思路再写代码;不搜题解(在提交三次错误之前);向队友讲述你的思路,做到简洁易懂;AC后回顾解题过程,总结出有价值的东西(思考问题的方式,调试代码的经验),写出一句话的题解。把你的感受出成题目为难队友。
每晚九点后,总结一天的训练情况,写成训练日记。发布到博客,11点验收。

集训的时候,除了前两个专题是热身训练,后来每周老师都会布置新的专题,会给出新的学习资料。当然每周除了个人刷题外,周二和周四下午也会有团队赛,三人组队去找比赛的感觉。

这次集训,本就是为了提高我们的个人实力和团队的协作能力。

专题一是图论和搜索的知识点,主要是为了弥补上学期只是学了知识点但却没有做题的缺失。

专题二就到了数据结构这部分单调队列和单调栈这部分题目。

专题三是树状数组和线段树的有关题目。

集训以刷题为主,也不是盲目的刷题,而且不断的巩固和提高自己的知识储备;

另外就是严格的按照比赛的条件去刷真题,找比赛的感觉,给自己定位,再有就是去参加真正的比赛,比如8月19日的2017年ccpc网络赛。题目难度很大。很受刺激,后来研究题解就研究了两三天。

通过这次暑假集训,给我带来了很大的收获,不光是知识量上更加的丰富,还有对自己耐心的磨练上,更加的有耐心了,还有磨练了自己的承受能力,有的时候一上午出不来一个题,练习赛的时候看着大佬们疯狂的a题,自己在一个题上不停的tle,谁能受的了啊,这需要一颗强大的心脏,此外还有对于程序的编写和程序的优化程度上都有很大的提高。最后希望自己和跟我一起集训的同学们能够在acm的路上越走越远!!

 


原创粉丝点击