上次我们学了dfs,深度优先搜索。
深搜有个缺点,就是“不撞南墙不回头”的遍历太暴力了,所以可能会时间超限,但是代码好写。
我们今天还是来学搜索——宽度优先搜索,bfs。
宽度优先搜索就像涟漪,一圈一圈的向外找。相当于树的层次遍历。搜完一层再搜一层·。
假设你现在站在一个路口的n点,你从地图里知道这附近一共k个商店,你想知道你从这里到m号商店,最少经过多少个商店。这样你有可能会从你的位置向外找路,因为这样效率高。你看,你在心中运行了BFS。
bfs是一种比较暴力的搜索(比dfs还暴力?),不搜到目标就不停,就是说你得一直找下去,不断地向外找,直到你找到了那个店。如果你真的这么干的,会累死的。
我送你一段模板代码,剩下的给我自己写去!!
void bfs()
{
front=rear=0;
a[sx][sy]=标记,不能走的;
qx[rear]=sx,qy[rear++]=sy;
step[sx][sy]=0;
while(front!=rear)
{
int tx=qx[front];
int ty=qy[front++];
if(目标状态)
{
执行目标操作;
return;
}
for(int i=0;i<4;i++)
{
int fx=tx+dx[i],fy=ty+dy[i];
if(越界)
{
continue;
}
if(没走过这个点,也就是这个点能走)
{
当前点入队;
qx[rear]=fx;
qy[rear++]=fy;
a[fx][fy]=标记上;
}
}
}
}
这是基本的bfs代码,因为这个模板是搜图的,要加方向数组。看着就暴力,没走过就走,记住这个路,我走过了不再走了,最后找到目标,好了,发送数值,你的任务完成了。
其实很适用于飞机搜目标。看看地上的路,搜完一条,没有,记住这条路别再搜了,然后再找。如果目标不移动,这样就算花一天,你也十有八九能找到他。
感觉好暴力啊……
不说了,做题吧……
小可走迷宫
时间限制:2秒 内存限制:256M
题目描述
小可置身于一个迷宫,每走一步只能向上下左右四个方向移动,请你帮小可找出从起点到终点的最短路程。
输入描述
输入包含多组测试数据。输入的第一行是一个整数T,表示有T组测试数据。
每组输入的第一行是两个整数N和M(1<=N,M<=100)。
接下来N行,每行输入M个字符,每个字符表示迷宫中的一个小方格。
字符的含义如下:
‘S’:起点
‘E’:终点
‘-’:空地,可以通过
‘#’:障碍,无法通过
输入数据保证有且仅有一个起点和终点。
输出描述
对于每组输入,输出从起点到终点的最短路程,如果不存在从起点到终点的路,则输出-1。
样例
输入
1 5 5 S-### ----- ##--- E#--- ---##
输出
9
这里我要提醒一下,宽搜是不用那么麻烦求最小步数的。因为宽搜的思想原因,他找出来的必定是最短路。但是这个不是GPS用的算法,GPS用的叫迪杰斯特拉,算最短路比这个还快,我后面会讲。
这个很明显的宽搜,但是宽搜有个毛病,他需要在传参数的时候判断终点。深搜就不这样,深搜是在搜的时候看看有没有到终点。
这个题终点条件是‘E’。所以我们先把主函数写好:
int main(){
for(int k=0;k<t;k++){
ff=0;
memset(step,0,sizeof step);
cin>>x>>y;
for(int i=1;i<=x;i++)
{
for(int j=1;j<=y;j++)
{
cin>>a[i][j];
if(a[i][j]=='S') sx=i,sy=j;
if(a[i][j]=='E') ex=i,ey=j;
}
}
//输出,特判-1
}
}
我还是只给一部分,剩下的自己写!!
bfs函数基本照抄模板,只要改几个判断就好了。这里我不给代码了,自己试着改一下,有问题找我调。
接下来我们再来一个:
奇怪的电梯
题目描述
假设一栋大楼有一种很奇怪的电梯。大楼的每一层楼都可以停电梯,而且第i层楼(1<=i<=N)上有一个数字Ki(0<=Ki<=N)。电梯只有四个按钮:开,关,上,下。上下的层数等于当前楼层上的那个数字。当然,如果不能满足要求,相应的按钮就会失灵。例如:3 3 1 2 5代表了Ki(K1=3,K2=3,……),从一楼开始。在一楼,按“上”可以到4楼,按“下”是不起作用的,因为没有-2楼。那么,从A楼到B楼至少要按几次按钮呢?
输入描述
第1行为3个正整数,表示N,A和B,1<=N<=200,1<=A,B<=N;
第2行为N个正整数,表示Ki。
输出描述
一行,共一个数,即最少按键次数。若无法到达,则输出-1。
样例
输入
5 1 5 3 3 1 2 5
输出
3
解析:
不很明显,电梯跟搜索哪门子关系?实际这也是宽搜。
一看至少,马上明白。按楼层搜就好了。
代码不给了,自己写吧,有事找我
家庭作业:
迷宫
时间限制:1秒 内存限制:128M
题目描述
一天小可在森林里探险的时候不小心走入了一个迷宫,迷宫可以看成是由n * n的格点组成,每个格点只有2种状态,.和#,前者表示可以通行后者表示不能通行。同时当小可处在某个格点时,他只能移动到东南西北(或者说上下左右)四个方向之一的相邻格点上,小可想要从点A走到点B,问在不走出迷宫的情况下能不能办到。如果起点或者终点有一个不能通行(为#),则看成无法办到。
输入描述
第1行是测试数据的组数k,后面跟着k组输入。每组测试数据的第1行是一个正整数n (1 ≤ n ≤ 100),表示迷宫的规模是n * n的。接下来是一个n * n的矩阵,矩阵中的元素为.或者#。再接下来一行是4个整数ha, la, hb, lb,描述A处在第ha行, 第la列,B处在第hb行, 第lb列。注意到ha, la, hb, lb全部是从0开始计数的。
输出描述
k行,每行输出对应一个输入。能办到则输出“YES”,否则输出“NO”。
样例
输入
2 3 .## ..# #.. 0 0 2 2 5 ..... ###.# ..#.. ###.. ...#. 0 0 4 0
输出
YES NO
注意啊是个多组输入,要while输入
好了,下课吧。下次我们讲位运算和用位运算优化的搜索。