浅谈搜索算法在信息学竞赛中的应用.docx
- 文档编号:5414275
- 上传时间:2022-12-16
- 格式:DOCX
- 页数:8
- 大小:36.60KB
浅谈搜索算法在信息学竞赛中的应用.docx
《浅谈搜索算法在信息学竞赛中的应用.docx》由会员分享,可在线阅读,更多相关《浅谈搜索算法在信息学竞赛中的应用.docx(8页珍藏版)》请在冰豆网上搜索。
浅谈搜索算法在信息学竞赛中的应用
浅谈搜索算法在信息学竞赛中的应用
SearchAlgorithminInformatics
【前言】
在信息学竞赛日渐普及,信息技术越来越重要的今天,搜索算法,一种充分利用计
算机计算速度遍历所有可能解的算法,被认为非常基础也非常重要。
让我们走近这听起
来非常高端的算法,一窥其真面目。
【摘要】
本文对搜索算法的两个分支——深度优先搜索(dfs)和广度优先搜索(bfs)展开
了研究,并通过在例题中的各种应用分析两种搜索方法的优化,对这一类的算法进行了
通用总结。
【关键词】
搜索算法信息学深度优先搜索广度优先搜索DFSBFS剪枝
【研究过程】
主要算法
(1)深度优先搜索(dfs)
深度优先搜索属于图算法的一种,英文缩写为DFS即DepthFirstSearch.其过程简要来说是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次。
主要用于图的搜索,但是在许多别的领域也有广泛应用。
举例说明之:
下图是一个无向图,如果我们从A点发起深度优先搜索(以下的访问次序并不是唯一的,第二个点既可以是B也可以是C,D),则我们可能得到如下的一个访问过程:
A->B->E(没有路了!
回溯到A)->C->F->H->G->D(没有路,最终回溯到A,A也没有未访问的相邻节点,本次搜索结束).
让我们先看一道经典例题。
【深度搜索基础】迷宫路径(深搜)
Description
这是实验心理学中的一个经典问题,心理学家把一只老鼠从一个无顶盖的大盒子的入口处赶进迷宫。
迷宫中设置很多隔壁,对前进方向形成了多处障碍,心理学家在迷宫的唯一出口处放置了一块奶酪,吸引老鼠在迷宫中寻找通路以到达出口。
迷宫以一个01矩阵表示,0表示通路,1表示不通,入口在座标(1,1),出口在(m,n),m表示行,n表示列。
老鼠在某一格子时,可以向周围8个格子移动(只要目的格子不为1或没有超出边界)。
现求解出到达出口的最少移动步数,注:
站在(m,n)即表示已经抵达出口,起始时老鼠站在(1,1)处。
这道题的基本思路是以(1,1)即起点为起始点,不断地通过递归来拓展每一个可能节点,直到找到终点或无路可走为止。
在遍历所有可能路径的同时统计最短的一条路,输出答案即可。
实际c++代码如下:
∙#include
∙#include
∙usingnamespacestd;
∙intg[52][52],n,m,xmin=10000;
∙struct{
∙intx;
∙inty;
∙}xx[8];
∙voidx(intnn,intmm,intc);
∙main()
∙{
∙ints,ss;
∙xx[0].x=0;xx[0].y=1;xx[1].x=1;xx[1].y=1;
∙xx[2].x=1;xx[2].y=0;xx[3].x=1;xx[3].y=-1;
∙xx[4].x=0;xx[4].y=-1;xx[5].x=-1;xx[5].y=-1;
∙xx[6].x=-1;xx[6].y=0;xx[7].x=-1;xx[7].y=1;
∙cin>>n>>m;
∙for(s=0;s<=n+1;s++){g[s][0]=1;g[s][m+1]=1;}
∙for(s=0;s<=m+1;s++){g[0][s]=1;g[n+1][s]=1;}
∙for(s=1;s<=n;s++)
∙for(ss=1;ss<=m;ss++)
∙cin>>g[s][ss];
∙x(1,1,0);
∙if(xmin==10000)cout<<"no";
∙elsecout< ∙} ∙voidx(intnn,intmm,intc) ∙{ ∙ints; ∙if((nn==n&&mm==m)&&(c ∙xmin=c; ∙} ∙elseif(c ∙for(s=0;s<=7;s++){ ∙if(g[nn+xx[s].x][mm+xx[s].y]==0){ ∙g[nn+xx[s].x][mm+xx[s].y]=2; ∙x(nn+xx[s].x,mm+xx[s].y,c+1); ∙g[nn+xx[s].x][mm+xx[s].y]=0; ∙} ∙} ∙} ∙ 这段代码中应用了标志数组的小技巧,使程序更加简洁明了。 同时,我们可以发现这种算法在最不利情况下的时间效率其实非常低,所以在这里加了非常有效的可行性剪枝,使效率大大提高。 关于一些剪枝方法,我会在后文谈到。 (2)广度优先搜索(bfs) 宽度优先搜索算法(又称广度优先搜索)是最简便的图的搜索算法之一,这一算法也是很多重要的图的算法的原型。 Dijkstra单源最短路径算法和Prim最小生成树算法都采用了和宽度优先搜索类似的思想。 其别名又叫BFS,属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。 换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。 在bfs中,通常使用先进先出队列(一种数据结构)来维护,并通过判重使搜索规模得到控制,避免做无用功,重复搜索同样的状态。 如图所示: 以1为起点,8为终点,路径长度为1。 在图中,我们可以通过路径段数把整个图划分成三层,其中,2,3,4是由1直接拓展出的节点,先把他们加入队列。 接下来取出2,通过2拓展出5,6两个节点并加入队列。 下一步取出3,通过3拓展出6,7。 需要注意的是,此时6已经在队列中了,所以不需要再次入队,以后如果再遇到6也不需要入队,而且该情况仅对路径长度为1时适用。 依此类推,当取出的节点为终点时就可以结束搜索了。 我们再来看看例题。 【宽度搜索基础】奇怪的电梯(宽搜) Description 呵呵,有一天我做了一个梦,梦见了一种很奇怪的电梯。 大楼的每一层楼都可以停电梯,而且第i层楼(1<=i<=N)上有一个数字Ki(0<=Ki<=N)。 电梯只有四个按钮: 开,关,上,下。 上下的层数等于当前楼层上的那个数字。 当然,如果不能满足要求,相应的按钮就会失灵。 例如: 33125代表了Ki(K1=3,K2=3,……),从一楼开始。 在一楼,按“上”可以到4楼,按“下”是不起作用的,因为没有-2楼。 那么,从A楼到B楼至少要按几次按钮呢? 这道题的思路和上面的最短路径其实有异曲同工之妙。 按一次按钮相当于走过路径长度为一的路,到达的每层楼则相当于上图中的节点,但是哪两条节点间有通路呢? 这就要看每层楼上的Ki值了,如果某层楼楼层数+/-Ki=另一楼层数,那么这两个节点间就有长度为1的边相连。 具体代码如下: ∙#include ∙#include ∙usingnamespacestd; ∙voidlift(intx,intc,intz); ∙intg[100],N,A,B,front,rear,step[201],ss=0; ∙boolboo[201],arrive=false; ∙intki[201]; ∙intmain() ∙{ ∙ints; ∙memset(boo,true,sizeof(boo)); ∙cin>>N>>A>>B; ∙for(s=1;s<=N;s++)cin>>ki[s]; ∙if(A! =B){ ∙boo[A]=false; ∙g[0]=A; ∙front=0; ∙step[g[front]]=0; ∙rear=1; ∙while(front! =rear){ ∙lift(g[front],step[g[front]],1); ∙lift(g[front],step[g[front]],2); ∙if(arrive)break; ∙front++; ∙front=front%100; ∙} ∙if(ss==0)cout<<-1< ∙elsecout< ∙} ∙elsecout<<0< ∙return0; ∙} ∙voidlift(intx,intc,intz) ∙{ ∙if(z==1){ ∙x=x+ki[g[front]]; ∙if(boo[x]&&(x>0)&&(x<=N)){ ∙boo[x]=false; ∙step[x]=c+1; ∙g[rear]=x; ∙rear++; ∙rear=rear%100; ∙} ∙if(x==B){arrive=true;ss=step[x];} ∙} ∙else{ ∙x=x-ki[g[front]]; ∙if(boo[x]&&(x>0)&&(x<=N)){ ∙boo[x]=false; ∙step[x]=c+1; ∙g[rear]=x; ∙rear++; ∙rear=rear%100; ∙} ∙if(x==B){arrive=true;ss=step[x];} ∙} ∙} 1、优化方法: 剪枝 (一)剪枝的原则 原则之一: 正确性。 因为它能够“剪去”搜索树中的一些“枝条”。 然而,如果在剪枝的时候,将“长有”我们所需要的解的枝条也剪掉了,那么,一切优化也就都失去了意义。 所以,对剪枝的第一个要求就是正确性,即必须保证不丢失正确的结果,这是剪枝优化的前提。 我们利用“必要条件”来进行剪枝判断。 也就是说,通过解所必须具备的特征、必须满足的条件等方面来考察待判断的枝条能否被剪枝。 这样,就可以保证所剪掉的枝条一定不是正解所在的枝条。 原则之二: 准确性。 即能够尽可能多的剪去不能通向正解的枝条。 准确性可以说是剪枝优化的生命。 原则之三: 高效性。 经常还需要提高判断操作本身的时间效率。 综上所述,我们可以把剪枝优化的主要原则归结为六个字: 正确、准确、高效。 (二)剪枝方法 1、可行性剪枝 搜索过程可以看作是对一棵树的遍历。 在很多情况下,并不是搜索树中 的所有枝条都能通向我们需要的结果,很多的枝条实际上只是一些死胡同。 如果我们能够在刚刚进入这样的死胡同的时候,就能够判断出来并立即剪 枝,程序的效率往往会得到提高。 而所谓可行性剪枝,正是基于这样一种考 虑。 2、最优性剪枝 在我们平时遇到的问题中,有一大类是所谓最优化问题,即所要求的结果是最优解。 此时就可以利用最优性剪枝来简化搜索复杂度。 在搜索的过程中,一般情况下,我们需要保存一个“当前最优解”,实际上就是保存解的优度的一个下界。 在遍历到搜索树的叶子节点的时候,我们就能得到一个新的解,当然也就得到了它的评价函数值,如果新解更优则更新优值下限。 搜索结束后,所保存的解就是最优解。 那么,最优性剪枝又是如何进行的呢? 当我们处在搜索树的枝条上时,可以通过某种方法估算出该枝条上的所有解的评价函数的上界,即所谓估价函数。 显然,大于当前保存的优度的下界,是该枝条上存在最优解的必要条件,否则就一定可以剪枝。 所以,最优性剪枝也可以称为“上下界剪枝”。 同时,我们也可以看到,最优性剪枝的核心问题就是估价函数的建立。 对这种剪枝方法应用最典型的就是A*算法,其效率很大程度上由估价函数的优劣左右,所以建立有效的估价函数也是程序取得高效率的重点。 【研究结论】 搜索在信息学奥赛中是非常有效的算法,当我们真正利用好各种优化方法时,搜索的效率能够大大提升,帮助我们解决许多难题。 我们不应该轻视基础的搜索算法,而是应该认真地把搜索吃透。 对于生活中许多其他问题也是一样,对待基础知识的正确方法是认真弄懂,踏踏实实地前进,这种思想将会对我们起巨大的帮助。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 浅谈 搜索 算法 信息学 竞赛 中的 应用