之前我们提到,小牛在解救小熊的时候,采用的是DFS深度优先搜索,今天我们将尝试另一种解酒方法:广度优先搜索——BFS。
我们还是用二维数组存储迷宫,最开始小牛在(1,1)处,他可以选择往右走或者往下走。这里我们选择“一层一层的走”。小牛一步之内可以到达(1,2)和(2,1)。但是小熊不在这里,那么小牛只能通过(1,2)和(2,1)这两个点继续往下走。比如小牛走到了(1,2),之后他又可以走到哪些新的点呢?即(2,2),再看看通过(2,1)又可以到达哪些点呢?有(2,2)和(3,1)。此时可以发现:(2,2)这个点既可以从(1,2)到达,也可以从(2,1)到达,并且都只走了2步,为了防止重复走过同一个点,这里使用数组来记录一个点是否被走过。
此时小牛2步可以走到的点就全部走到了,即(2,2)和(3,1),但是小熊不在这两个点上,那么小牛就要再接着看看,通过这两个点,还可以到达哪些新的点?通过(2,2)可以到达(2,3)和(3,2),通过(3,1)可以到达(3,2)和(4,1)。现在三步可以到达的点有(2,3)、(3,2)、和(4,1),依旧没找到小熊,所以小牛需要重复上诉操作。
这里,我们用一个结构体来实现队列
struct note{
int x;//横坐标
int y;//纵坐标
int s;//步数
};
struct node que[2501];
int a[51][51];//存储地图
int head,tail;
int book[51][51];//存储哪些点在队列中,防止重复走
head=1;
tail=1;
que[tail].x = 1;
que[tail].y = 1;//将(1,1)加入队列
que[tail].s = 0;
tail++;
book[1][1] = 1;//并且记录(1,1)已经走过
然后从(1,1)开始,先尝试往右走达到了(1,2):
tx = que[head].x;
ty = que[head].y+1;
if(tx<1 || tx>n || ty<1 || ty>m)//判断(1,2)是否越界
continue;
if(a[tx][ty]==0 && book[tx][ty]==0){
book[tx][ty] = 1;
que[tail].x = tx;
que[tail].y = ty;
que[tail].s = que[head].s +1; //步数是父亲步数+1
tail++;
}
接下来还要尝试往其它方向走,这里和之前讲深度优先搜索的时候一样,规定一个顺序:顺时针方向来尝试路径(即:右下左上)
当我们对(1,1)拓展完毕后,(1,1)对我们已经没有用了,此时我们将(1,1)出队,这里的语句很简单,就一句话: head++;
接下来我们需要在刚刚新拓展的(1,2)和(2,1)这两个点的基础上继续往下走,将(1,1)出队后,现在队列的head正好指向了(1,2),现在小牛需要通过这个点继续拓展,通过(1,2)可以到达(2,2),并将(2,2)也加入队列。
我们只需要重复实现以上操作就好。
完整代码如下
#include<stdio.h>
struct node{
int x;//横坐标
int y;//纵坐标
int s;//步数
};
int main(){
struct node que[2501];//根据地图大小开数组大小
int a[51][51]={0};
int book[51][51] = {0};
int next[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
int head,tail;
int i,j,k,n,m,startx,starty,p,q,tx,ty,flag;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
scanf("&d&d&d&d",&startx,&starty,&p,&q);
head = 1;
tail = 1;
que[tail].x = startx;
que[tail].y = starty;
que[tail].s = 0;
tail++;
book[startx][starty] = 1;
flag = 0; //用来标记是否达到目标点
while(head<tail){
for(k=0;k<=3;k++){
tx = que[head].x + next[k][0];
ty = que[head].y + next[k][1];
if(tx<1 || tx>n || ty<1 || ty>m)
continue;
if(a[tx][ty]==0 && book[tx][ty]==0){
//把这个点标记已走过
book[tx][ty] = 1;
que[tail].x = tx;
que[tail].y = ty;
que[tail].s = que[head].s+1;
tail++;
}
// 如果到达位置,停止拓展
if(tx==p && ty==q){
flag = 1;
break;
}
}
if(flag==1)
break;
head++;//当一个点拓展结束后,才可以对下面的点进行拓展
}
printf("%d",que[tail-1].s);
return 0;
}
: