哈哈哈,上一篇suo了深搜,自然,广搜来了,其实宽度优先搜索能干的事深搜一般也能胜任,广搜常用于找单一的最短路线,它的特点是 “搜到就是最优解”,在空间足够的情况下找最优解可以使用广搜
直接把上次那个题拿来充个数:
题目背景
给定一个N*M方格的迷宫,迷宫里有T处障碍,障碍处不可通过。给定起点坐标和终点坐标,问: 每个方格最多经过1次,有多少种从起点坐标到终点坐标的方案。在迷宫中移动有上下左右四种方式,每次只能移动一个方格。数据保证起点上没有障碍。
输入格式
第一行N、M和T,N为行,M为列,T为障碍总数。第二行起点坐标SX,SY,终点坐标FX,FY。接下来T行,每行为障碍点的坐标。
输出格式
给定起点坐标和终点坐标,问每个方格最多经过1次,从起点坐标到终点坐标最短步数
给一个简单的数据我们先来分析一下
4 4 3
1 1 4 4
2 2
3 2
3 3
好像不是很直观哈哈,给整个图,就这个亚子叭:
再给整个编号
我们先规定,到每个新节点,按右,下,上,左的顺序尝试;那么我们一步一步分析;
先放个流程图,哈哈哈
要完成上面的步骤,我们可以这样:
- 每一步都尝试能走的所有方向,能走通就往下走
- 走过的结点不再走
- 只要有一种方式到终点就输出步数
然后我们会发现,和深搜不通的是,广搜走着走着某一步会有很多很多个节点都可以继续往下走,为了保存上一步的节点(们),我们用一个队列来模拟
具体呢就是让头指向上一步的第一个一个节点,然后每处理一个节点就让head++;这样就实现了在进入下一步前,处理的每一个方向都是这一步的,因为广搜本来就是用来找最短路径,所以这样做可以实现
举个例子:
== 蓝色的是top,橘色的是tail==
看图,,,前两张新增了由第一步第一个节点新产生的两个节点,
然后第一步第二个节点新产生的两个节点
此时当top继续后移就进入下一步继续上面的步骤
可以发现,某一步所走的所有节点都在一起,这就是广搜的效果了
介绍到这里就结束了,其实广搜也可以当作模拟来看,上面的步骤已经给了,下面放代码
#include<stdio.h>
struct node
{
int x;
int y;
int bs;
}list[10000];//用一个队列来模拟
int main()
{
int i,sd,aa,bb,sx,sy,tx,ty,cc=0;
int a[100][100]={0},book[100][100]={0},n,m;
int ex,ey;
int flag=0;
int top=0,tail=0;
int next[4][2]{{0,1},{1,0},{0,-1},{-1,0}};
scanf("%d%d%d",&n,&m,&sd);
scanf("%d%d",&sx,&sy);
scanf("%d%d",&ex,&ey);
for(i=0;i<sd;i++)
{
scanf("%d%d",&aa,&bb);
a[aa][bb]=1;
}
book[sx][sy]=1;
//插入第一个节点
list[tail] .x=sx;
list[tail].y=sy;
list[tail].bs=0;
tail++;
cc=0;//用来标记是否到达终点;
while(tail>top)
{
for(i=0;i<4;i++) //遍历top所指节点的所有下一步
{
tx=list[top].x+next[i][0];ty=list[top].y+next[i][1];
if(tx<1||tx>n||ty<1||ty>m) //判断边界
{
continue;
}
if(a[tx][ty]==0&&book[tx][ty]==0) //判断能否走通
{
book[tx][ty]=1;
list[tail].x=tx;
list[tail].y=ty;
list[tail].bs=list[top].bs+1;
tail++;
}
if(tx==ex&&ty==ey) //走到终点了
{
cc=1;
break;
}
}
if(cc==1)
{
break;
}
top++; //这个节点所有操作结束,top++继续下一个节点
}
printf("%d",list[tail-1].bs);
return 0;
}