初学bfs广度优先搜索&洛谷【马的遍历】题解

我对广度优先搜索(BFS)的理解

广度优先搜索(BFS)是一种常见的图和树的遍历算法,其基本思想是按照深度从浅到深的顺序访问图或树中的节点。它从根节点开始(也可以是其他指定的节点),然后探索所有相邻的节点,然后再探索这些节点的相邻节点,以此类推。BFS使用队列数据结构来存储待访问的节点,遵循“先入先出”的原则。BFS常用于迷宫问题,最短路径等问题的求解。

学习广搜的艰难历程

与dfs不同的是bfs需要用队列来存储节点,一开始看的很多讲解视频和帖子都是用的C++直接请求一个队列(C好像是不能这么玩的,C++我又不会,当时也不会用C写队列),虽然基本都有解释队列的使用过程,但是都没有给出队列的源代码,以至于我一直不知道如何在C中实现队列。最后我还是决定专门去学习一下队列在C语言中的实现。我首先是在《啊哈算法》这本书中了解到了最简单的C语言队列的实现,原码如下:

初学bfs广度优先搜索&洛谷【马的遍历】题解_第1张图片

初学bfs广度优先搜索&洛谷【马的遍历】题解_第2张图片

这样写简单易懂,但是会对空间有很大的浪费,这显然不是我想要的版本。然后是在小破站了解到了循环队列,结合《啊哈算法》中的队列实现这才得以完成BFS后面的学习。

洛谷【马的遍历】题解

刚搞懂bfs我就迫不及待的写了这一题

原题点这里-->P1443 马的遍历 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

题目描述

有一个 n×m 的棋盘,在某个点 (x,y) 上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步。

输入格式

输入只有一行四个整数,分别为 n,m,x,y。

输出格式

一个 n×m 的矩阵,代表马到达某个点最少要走几步(不能到达则输出 −1−1)。

输入输出样例

输入 #1

3 3 1 1

输出 #1

0    3    2    
3    -1   1    
2    1    4    

数据规模与约定

对于全部的测试点,保证 1≤x≤n≤400,1≤y≤m≤400。

源代码

想说的话都在注释里了

#include

#define MAX_SIZE 10000//这里决定了队列的大小,开小了队列可能会爆掉导致出错 

typedef struct{
	int data[MAX_SIZE][2];//开二维数组因为要存横纵坐标 
	int front;
	int rear;
}CircularQueue;//这是我们要用的队列

int dx[8]={2,2,1,-1,-2,-2,-1,1};
int dy[8]={-1,1,2,2,1,-1,-2,-2};//分别对应马的八个走向 


int n,m,a[402][402],p,q;//数组a用来记录走到该点的步数,p,q分别为起始点的横纵坐标 



int main()
{
	scanf("%d%d%d%d",&n,&m,&p,&q);
	
	CircularQueue queue;
	queue.front=queue.rear=0;//定义一个队列并初始化 
	
	queue.data[queue.rear][0]=p;
	queue.data[queue.rear][1]=q;
	queue.rear=(queue.rear+1)%MAX_SIZE;//将起始点入队 
	
	while(queue.front!=queue.rear)//当队空时结束 
	{
		for(int i=0;i<8;i++)//试探马下一步可能走到的八个位置 
		{
			int x=queue.data[queue.front][0]+dx[i];
			int y=queue.data[queue.front][1]+dy[i];
			if(x>0&&x<=n&&y>0&&y<=m&&(x!=p||y!=q)&&a[x][y]==0)//入队的条件 
			{
				a[x][y]=a[queue.data[queue.front][0]] [queue.data[queue.front][1]]+1;//标记走到该点所花的步数 
				queue.data[queue.rear][0]=x;
				queue.data[queue.rear][1]=y;
				queue.rear=(queue.rear+1)%MAX_SIZE;//入队 
			}
		}
		queue.front=(queue.front+1)%MAX_SIZE;//队首出队
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)//双重for循环遍历棋盘用于输出结果 
		{
			if(a[i][j]==0)//值为零时可能是起始点也可能是到达不了,所以要再判断一下 
			{
				if(i==p&&j==q)
				printf("0    ");
				else
				printf("-1    ");
			}
			else
			printf("%d    ",a[i][j]);
		}
		printf("\n");
	 } 
	
	return 0;
}

 小结

广度优先搜索在使用队列时要特别注意入队的条件,还有对已到达位置的标记。

发现撒子问题记得提醒我呦

你可能感兴趣的:(宽度优先,算法,c语言)