集训总结

1.搜索和图论

1.1搜索

1.1.1 广度优先搜索

广度优先搜索算法,简称BFS,是最简便的图的搜索算法之一。该算法自始至终一直通过已找到和末找到顶点之间的边界向外扩展,最简单直观的例子就是走迷宫,我们从起点开始,找出到终点的最短路程,很多最短路径算法就是基于广度优先的思想成立的。首先访问起始顶点a,接着由a出发,依次访问a的各个未访问过的邻接顶点b1,b2,…,bi,然后再依次访问b1,b2,…,bi的所有未被访问过的邻接顶点;再从这些访问过的顶点出发,再访问它们所有未被访问过的邻接顶点……依次类推,直到图中所有顶点都被访问过为止。广度优先搜索是一种分层的查找过程,辐射状的优先遍历。每向前走一步可能访问一批顶点,为了实现逐层的访问,算法必须借助一个辅助队列,以记录正在访问的顶点的下一层顶点。

广度优先搜索的经典题目是catch that cow。题意是FJ要抓奶牛。开始输入N(FJ的位置)K(奶牛的位置)。FJ有三种移动方法:1、向前走一步,耗时一分钟。2、向后走一步,耗时一分钟3、向前移动到当前位置的两倍N*2,耗时一分钟。问FJ抓到奶牛的最少时间。在起点分别用三种情况搜索,得到的分别入队,再分别把他当做起点重新遍历。广度优先搜索关键是不走重复的路与记录路径,尽量的剪枝。

1.1.2 深度优先搜索

深度优先搜索,简称DFS,其过程简要来说是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次。深度优先搜索是递归的过程,假设初始状态是图中所有顶点均未被访问,则从某个顶点a出发,首先访问该顶点,然后依次从它的各个未被访问的邻接点出发深度优先搜索遍历图,直至图中所有和a有路径相通的顶点都被访问到。 若此时尚有其他顶点未被访问到,则另选一个未被访问的顶点作起始点,重复上述过程,直至图中所有顶点都被访问到为止。简单说就是遇到分叉路选一个走到底,发现走不通就掉头走另一个路口,直到找到正确的路为止。

广度优先搜索的经典题目有很多,最经典的题目是八皇后问题和跳马问题,八皇后问题是指在8*8格的国际象棋棋盘上安放8个皇后,让它们不能相互攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。我们每取出一个皇后,放入一行,共有八种不同的放法,然后再放第二个皇后,同样如果不考虑规则,还是有八种放法。于是我们可以用一个八叉树来描述这个过程。从根节点开始,树每增加一层,便是多放一个皇后,直到第8层(根节点为0层),最后得到一个完全八叉树。紧接着我们开始用深度优先遍历这个八叉树,在遍历的过程中,进行相应的条件的判断。以便去掉不合规则的子树。八皇后还有很多种变形这里就不一一列举了。简单的跳马问题,要求在64个国际象棋格子,任意位置放一个马,如何不重复地把格子走完,也就像刚才的完全八叉树,只不过吧判断条件改了一下。深度优先搜索关键是及时的判断走的路错了掉头和记录路径。

1.2图论

1.2.1一笔画问题与哈密尔顿环

欧拉路是一个图一笔画的路径,如果最后又回到起点,那这个路径叫做欧拉回路。存在欧拉路的条件:图是连通的,跟这个点相连的边数目有奇数个的点只有2个。存在欧拉回路的条件是图是连通的,没有跟这个点相连的边数目有奇数个的点。求欧拉路的算法很简单,使用深度优先遍历即可。根据一笔画的两个定理,如果寻找欧拉回路,对任意一个点执行深度优先遍历;找欧拉路,则对一个奇点执行深度优先受搜索。哈密尔顿环是指不重复地走过所有的点,并且最后还能回到起点的回路。使用简单的深度优先搜索,就能求出一张图中所有的哈密尔顿环。

1.2.2最短路径算法

   最短路径算法有4种,其中最简单的最短路径算法是弗洛伊德算法,可以计算图中任意两点间的最短路径。虽然适用于出现负边权的情况但的时间复杂度是O (N3)。第二种算法是Dijkstra算法用来计算从一个点到其他所有点的最短路径的算法,是一种单源最短路径算法。也就是说,只能计算起点只有一个的情况。Dijkstra的时间复杂度是O (N2),它不能处理存在负边权的情况。Bellman-Ford算法也是一种单源最短路径算法。能够处理存在负边权的情况,但无法处理存在负权回路的情况。算法时间复杂度:O(NE),N是顶点数,E是边数。最后是SPFA算法SPFA是Bellman-Ford算法的一种队列实现,减少了不必要的冗余计算。初始时将起点加入队列。每次从队列中取出一个元素,并对所有与它相邻的点进行修改,若某个相邻的点修改成功,则将其入队。直到队列为空时算法结束。

1.2.3并查集

   并查集处理“集合”之间的关系,即动态地维护和处理集合元素之间复杂的关系,当给出两个元素的一个无序对(a,b)时,需要快速“合并”a和b分别所在的集合,这其间需要反复“查找”某元素所在的集合。“并”、“查”和“集”三字由此而来。在这种数据类型中,n个不同的元素被分为若干组。每组是一个集合,这种集合叫做分离集合。并查集支持查找一个元素所属的集合以及两个元素各自所属的集合的合并。并查集就有几个操作,初始化,寻找根节点编号并压缩路径,合并两个集合,判断元素是否属于同一集合。

1.2.4最小生成树

一个有N个点的图,边一定是大于等于N-1条的。图的最小生成树,就是在这些边中选择N-1条出来,连接所有的N个点。这N-1条边的边权之和是所有方案中最小的。求最小生成树有两种算法,第一种是PRIM算法每次循环都将一个蓝点u变为白点,并且此蓝点u与白点相连的最小边权min[u]还是当前所有蓝点中最小的。这样相当于向生成树中添加了n-1次最小的边,最后得到的一定是最小生成树。第二种是Kruskal算法,它巧妙利用并查集来求最小生成树。Kruskal首先将所有的边按从小到大顺序排序,并认为每一个点都是孤立的,分属于n个独立的集合,然后按顺序枚举每一条边。如果这条边连接着两个不同的集合,那么就把这条边加入最小生成树,这两个不同的集合就合并成了一个集合,如果这条边连接的两个点属于同一集合,就跳过。直到选取了n-1条边为止。

1.2.5拓扑排序

把AOV网中的所有活动排成一个序列, 使得每个活动的所有前驱活动都排在该活动的前面,这个过程称为“拓扑排序”,所得到的活动序列称为“拓扑序列”。选择一个入度为0的顶点并输出从AOV网中删除此顶点及以此顶点为起点的所有关联边;重复上述两步,直到不存在入度为0的顶点为止。若输出的顶点数小于AOV网中的顶点数,则输出“有回路信息”,否则输出的顶点序列就是一种拓扑序列。

2二分查找和单调队列

2.1二分查找

二分查找是一种查找速度快,查找次数少的一种算法,但其缺点是要求待查表为有序表,且插入删除困难。二分找方法适用于不经常变动而查找频繁的有序列表。首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。

2.2单调队列

单调队列,顾名思义是单调递减或单调递增的队列。单调队列有两种操作进队与出队进队时,将进队的元素为a,从队尾往前扫描,直到找到一个不大于a的元素b,将a放在b之后,舍弃a之后的所有元素;如果没有找到这样一个b,则将a放在队头(此时队列里只有这一个元素)。出队时,将出队的元素为a,从队头向后扫描,直到找到一个元素c比a后进队,舍弃c之前所有的。

3树状数组

树状数组一个查询和修改复杂度都为log(n)的数据结构。主要用于查询任意两位之间的所有元素之和,但是每次只能修改一个元素的值;经过简单修改可以在log(n)的复杂度下进行范围修改,但是这时只能查询其中一个元素的值。发现树装数组的应用不是单独出现的,更像一个工具,伴随的好多算法出现,更像一个优化,树装数组求逆序看数据范围,离散化适合给出的数据很大,而用不到值本身,这样就可以吧数压缩,压缩到非常小的数组里,然后求逆序数了,还有一种情况数据都在一个区间内,这样可以直接求逆序数,有的时候树状数组要求要两个一起用,需要注意两个数组的更新顺序。另外树状数组还可以区间更新单点查询,对原数组做拆分,即令的d[i] = a[i] – a[i-1],特别地d[i] = a[i].则a[i] = d[1] + d[2] + … + d[i]; 做单点查询就是在求d[1….i]的和。给整个区间[l, r]增加k,d[l] += k, d[r+1] -= k;维护的d数组。

4.总结

这一个月的训练,首先是写代码的能力上升了,不再像以前,想到什么思路而写不出来了。然后把以前学习的几种算法都融汇贯通了,打好了基础。再来与队友的配合越来越默契了,比赛的时候与队友不是一加一小于二了而是一加一大于二,又学习到了新的算法,可以解决掉部分以前超时的问题了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值