广度优先搜索—BFS

        之前我们提到,小牛在解救小熊的时候,采用的是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;
} 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值