BFS广搜总结

BFS

bfs也是一个对连通图进行遍历的算法。它的思想是从一个被选定的点出发;然后从这个点的所有方向齐头并进,每次只向前走一小步;如果得不到目的解,那就返回事先定好的值,如果找到直接返回目的解。
运用队列和函数内循环构造的。

dfs也可以找到最短路径,但是时间复杂度高;而且dfs能找到到终点的路径但是不一定是最短

但是BFS搜索到的结果一定是最短的

作用:

(1):求最短路径 最少操作 最小步数 最小时间 比如:求二叉树最小高度

(2):求联通块(与DFS类似)

结构:

其搜索路线是以一层一层、由近及远的顺序进行搜索,每一次向外扩展一步,最先推展到终点的那条路就是最短路径

理解BFS:

需要使用一个队列来实现一层一层访问节点的顺序

img

走法:

起始点为 a,终点为 f
求最少经过几个点能从点 a 到达点 f
第一层为起点,即点 a
第二层为点 a 能去到的位置,即点 b、c、d
第三层为点 b、c、d 能去到的位置,即点 e、f
此刻在第三层已经到达了点 f,即到达了终点。
那么我们便可以得出最少经过的点数了,即为 3 个点(a、d、f)

代码框架:
1.准备结构体:
//开一个结构体
struct point 
{
    int x;//结点所在位置
    int y;
    int step;//步数
};

2.编写BFS函数(二维)

const int maxn = ...;
int gx, gy;  // 终点的位置,在 main 里读入
int n, m;    // 图的边界,在 main 里读入
bool vis[maxn][maxn];  // 记录位置是否被走过
int map[maxn][maxn];   // 建一个二维数组来存放图的内容
// 以四个方向为例:上下左右
int dx[4] = {0,0,-1,1};
int dy[4] = {1,-1,0,0};

int bfs(int x, int y)
{
	queue<node>q;  // 开一个队列
	// 对起点初始化
	st.x = x;
	st.y = y;
	st.step = 0;  // 初始层次为 0
	memset(vis, false, sizeof(vis));
	vis[x][y] = true;  // 标记初始位置已被走过
	q.push(st);   // 先将起点放入队列
	
	while(!q.empty())  // 直到队列为空 或 找到终点后,终止循环
	{
		st = q.front();  // 将起点更新为队列中的第一个结构
		q.pop();  // 然后将队列中第一个结构删除
		
		// 找到终点,就结束函数,并返回此时层数
		if(st.x==gx && st.y==gy)
			return st.step;
		
		for(int i=0; i<4; i++)//四个方向试探
		{
			ed.x = st.x + dx[i];
			ed.y = st.y + dy[i];
			ed.step = st.step + 1; 
			
			// 若该位置已走过,则进入下一循环,避免重复
			// 若超出边界,则进入下一循环
			if(vis[ed.x][ed.y] || map[ed.x][ed.y]=='题目条件' || ed.x<0 || ed.x>=n || ed.y<0 || ed.y>=m)
				continue;
			
			vis[ed.x][ed.y] = true; //标记该位置已走过
			
			// 若还未到终点,则将其放入队列,变成下次调用的起点
			q.push(ed);
		}
	}
	return -1;  // 若找不到终点,则按题目要求返回特定值
}	

3.编写main函数

int main()
{
	int sx, sy;   //起点
	scanf("%d %d", &n, &m);    //读入边界
	scanf("%d %d", &sx, &sy);  //读入起点
	scanf("%d %d", &gx, &gy);  //读入终点
	
	for(int i=0; i<n; i++)
		for(int j=0; j<m; j++)
			scanf("%c", &map[i][j]);
	
	if(sx==gx && sy==gy)
		printf("0\n");
	else
		printf("%d\n", bfs(sx, sy));
	return 0;
}

一维

问题描述:奇怪的电梯

有一个奇怪的电梯。电梯可以根据需要在每个楼层停下罐头,每层楼都有一个数字Ki(0 <= Ki <= N)。升降机只有两个按钮:向上和向下。当你在i楼时,如果你下“UP”按钮,你将上Ki楼层,即你将进入i+Ki楼,同样,如果你按下“DOWN”按钮,你将下Ki楼层,即你将去i-Ki楼。当然,电梯不能上升到N以上,也不能下降到低于1。例如,有一个5层的建筑物,k1 = 3,k2 = 3,k3 = 1,k4 = 2,k5 = 5.从1楼开始,你可以按按钮“UP”,你会上到4楼,如果你按下按钮“DOWN”,电梯就做不到了,因为它不能下到-2楼,如您所知,-2楼不存在。
问题来了:当你在A楼,你想去B楼时,他至少要按多少次“上”或“下”按钮?

实际问题:求最少,因此考虑BFS

输入

第一行包含上面描述的三个整数N,A,B(1<= N,A,B <= 200),第二行包含N个整数k1,k2,…kn.
单个 0 表示输入结束。

输出

对于每种情况下的输入输出一个中间器,当你在A楼时,你必须按下按钮的次数最少,你想去B楼,如果你不能到达B楼,printf “-1”。

样例输入
5 1 5
3 3 1 2 5
0
样例输出
3
#include<iostream>
#include <queue>
using namespace std;

//结构体
struct node
{
	int x;//坐标:层数
	int step;
}st,ed;
queue<node> q;//申请队列

int sx,gx,n;
int a[205];
int v[205];//标记 1走过 0未走过
int bfs(int x)
{
	st.x=x;//初始化起点
	st.step=0;
	v[x]=1;//标记走过
	q.push(st);//将起点放入队列,注意这里写的是结构体的
	
	while(!q.empty()){//当队列不为空
       //
		st=q.front();//将起点放入队列中
		q.pop();//从队列中删掉
		
		if(st.x==gx){//到达终点 结束 返回步数
			return st.step;
		}
		for(int i=-1;i<=1;i+=2){
			ed.x=st.x+i*a[st.x];//不理解+的后半部分
			ed.step=st.step+1;
			//如果位置走过,则进入下一层循环,避免重读
			//超出边界,则进入下一层循环
			if(v[ed.x]==1 || ed.x>n || ed.x<=0){
				continue;
			}
			v[ed.x]=1;//标记已经走过
			q.push(ed);//如果还没有到达终点,就放入队列中,作为下一次的起点
		}
	}
	return -1;//题目要求到不了终点输出-1
}
int main()
{
	cin>>n>>sx>>gx;//n表示楼层数
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	if(sx==gx){
		cout<<0<<endl;
	}
	else{
		cout<<bfs(sx);//从起点开始
	}
	return 0;
}

一维

题目描述:

农夫约翰被告知一头逃跑的奶牛的位置,想立即抓住她。他从数线上的点 N(0 ≤ N ≤ 100,000)开始,母牛在同一条数线上的点 K (0 ≤ K ≤ 100,000)。农夫约翰有两种交通工具:步行和传送。

步行:FJ可以在一分钟内
从任何点X移动到点X-1或X + 1

传送:FJ可以在一分钟内从任何点X移动到2×X点。

如果这头牛不知道它的追逐,根本不动,农夫约翰需要多长时间才能取回它?

输入

第 1 行:两个空格分隔的整数:N 和 K

输出

第 1 行:农夫约翰抓住逃跑的牛所需的时间最短,以分钟为单位。

样例输入

5 17

样例输出

4

提示

农夫约翰到达逃逸牛的最快方法是沿着以下路径移动:5-10-9-18-17,需要 4 分钟。

代码:

#include <iostream>
#include <queue>
using namespace std;
//先定义结构体才能申请队列,顺序不能乱
struct node
{
	int x;//一条线上的位置
	int step;//时间
}st,ed;
queue<node> q;

int v[100005];//1表示已经访问
int sx,gx;

int bfs(int x)
{
	//队列
	st.x=x;
	st.step=0;
	v[x]=1;//标记:起点
	q.push(st);//将起点放入队列
	
	while(!q.empty())
	{
		st=q.front();//将起点更新为队列中的第一个结构体
		q.pop();
		
		if(st.x==gx){//判断有没有到终点
			return st.step;
		}
		//有三个分支,用for循环
		for(int i=0;i<3;i++){
			if(i==0){
				ed.x=st.x-1;
			}
			else if(i==1){
				ed.x=st.x+1;
			}
			else if(i==2){
				ed.x=st.x*2;
			}
			ed.step=st.step+1;
		    //位置访问过 超边界
		    if( ed.x<0 || ed.x>100005 || v[ed.x]==1)
			    continue;
			    
			v[ed.x]=1;
	        q.push(ed);
	    }
	}
	
}
int main()
{
	cin>>sx>>gx;
	if(sx==gx){
		cout<<0<<endl;
	}
	else{
		cout<<bfs(sx);
	}
	return 0;
}

二维

问题描述:骑士招式

你的一个朋友正在研究旅行骑士问题(TKP),在那里你要找到最短的骑士移动闭合之旅(最短路径),它只访问棋盘上给定n个方块的每个方格一次。他认为问题中最困难的部分是确定两个给定方格之间的最小骑士移动次数,一旦完成此操作,找到游览将很容易。
当然,您知道反之亦然。所以你让他写一个程序来解决“困难”的部分。 你的工作是编写一个程序,将两个正方形a和b作为输入,然后确定从a到b的最短路线上的骑士移动次数。

西洋棋中骑士的走法时:先横或竖1或2格,再竖或横2或1格,不只是走一格 因此骑士可能的走法有8种:

int dx[8] = {-2,-2,2,2,-1,-1,1,1};
int dy[8] = {-1,1,-1,1,-2,2,-2,2};
#include <stdio.h>
#include <queue>

struct node{
	int x, y;
	int step;
} st, ed;

int gx, gy;
int dx[8] = {-2,-2,2,2,-1,-1,1,1};
int dy[8] = {-1,1,-1,1,-2,2,-2,2};
//最关键!!!
int bfs(int x, int y)
{
	std::queue<node>q;
	st.step = 0;
	st.x = x;
	st.y = y;
	q.push(st);
	while(!q.empty())
	{
		st = q.front();
		q.pop();
		
		if(st.x==gx && st.y==gy)
			return st.step;
		
		for(int i=0; i<8; i++)
		{
			ed.x = st.x + dx[i];
			ed.y = st.y + dy[i];
			ed.step = st.step + 1;
			//边界
			if(ed.x<=0 || ed.x>8 || ed.y<=0 || ed.y>8) continue;
			q.push(ed);
		}
	}
	return -1;
}

int main()
{
	int sx, sy;
	char c1, c2;
	while(scanf("%c%d %c%d", &c1, &sy, &c2, &gy) != EOF)
	{
		getchar();
		sx = c1 - 'a' + 1;
		gx = c2 - 'a' + 1;
		if(sx==gx && sy==gy)
			printf("To get from %c%d to %c%d takes 0 knight moves.\n", c1, sy, c2, gy);
		else
			printf("To get from %c%d to %c%d takes %d knight moves.\n",c1, sy, c2, gy, bfs(sx, sy)); 
	}
	return 0;
}


C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。在编写C程序时,需要注意变量的声明和定义、指针的使用、内存的分配与释放等问题。C语言中常用的数据结构包括: 1. 数组:一种存储同类型数据的结构,可以进行索引访问和修改。 2. 链表:一种存储不同类型数据的结构,每个节点包含数据和指向下一个节点的指针。 3. 栈:一种后进先出(LIFO)的数据结构,可以通过压入(push)和弹出(pop)操作进行数据的存储和取出。 4. 队列:一种先进先出(FIFO)的数据结构,可以通过入队(enqueue)和出队(dequeue)操作进行数据的存储和取出。 5. 树:一种存储具有父子关系的数据结构,可以通过中序遍历、前序遍历和后序遍历等方式进行数据的访问和修改。 6. 图:一种存储具有节点和边关系的数据结构,可以通过广度优先索、深度优先索等方式进行数据的访问和修改。 这些数据结构在C语言中都有相应的实现方式,可以应用于各种不同的场景。C语言中的各种数据结构都有其优缺点,下面列举一些常见的数据结构的优缺点: 数组: 优点:访问和修改元素的速度非常快,适用于需要频繁读取和修改数据的场合。 缺点:数组的长度是固定的,不适合存储大小不固定的动态数据,另外数组在内存中是连续分配的,当数组较大时可能会导致内存碎片化。 链表: 优点:可以方便地插入和删除元素,适用于需要频繁插入和删除数据的场合。 缺点:访问和修改元素的速度相对较慢,因为需要遍历链表找到指定的节点。 栈: 优点:后进先出(LIFO)的特性使得栈在处理递归和括号匹配等问题时非常方便。 缺点:栈的空间有限,当数据量较大时可能会导致栈溢出。 队列: 优点:先进先出(FIFO)的特性使得
Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),可运行高分资源 Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值