广度优先搜索笔记

广度优先搜索


广度优先搜索又称为宽度优先搜索,简称bfs,与深度优先搜索不同的是,广度优先搜索会先将与起始点距离较近的点搜索完毕,再继续搜索较远的点,而深搜却是沿着一个分支搜到最后
bfs从起点开始,优先搜索离起点最近的点,然后由这个最近的点扩展其他稍近的点,这样一层一层的扩展,就像水波扩散一样
bfs需要借助队列实现:
1.初始的时候把起点放到队列中,并标记起点访问
2.如果队列不为空,从队列中取出一个元素x,否则算法结束
3.访问和x相连的所有点v,如果v没有被访问,把v入队,并标记已经访问
4.重复执行步骤2.
最后写出来的代码框架如下:

void bfs(起始点)
{
	//将起点放入队列中;
	//标记起点访问;
	while (如果队列不为空)
	{
		//访问队列中队列首元素x;
		//删除队首元素;
		for (x所有相邻的点)
		{
			if (该点未被访问过且合法)
			{
				//将该点加入队列末尾;
			}
		}
	}
	//队列为空,广搜结束;
}

用bfs解决迷宫问题

字符S表示起点,字符T表示终点,字符*表示墙壁,字符.表示平地。你需要从S出发走到T,每次只能向上下左右相邻的位置移动,不能走出地图,也不能穿过地图,每个点只能通过一次。你需要编程来求解出最短路径
使用求解迷宫最短路有一个很大的缺陷,需要枚举所有可能的路径,读入的地图一旦很大,可能的搜索方案数量会非常多,用dfs搜索显然效率会很低
我们可以通过bfs来求解迷宫问题,由于bfs是分层搜索,因此,第一次搜索到终点的时候,当前搜索的层数就是最短路径的长度

#include <iostream>
#include <string>
#include <queue>
using namespace std;
int n, m;
string maze[110];
bool vis[110][110];
int dir[4][2] = { {-1,0},{0,-1},{1,0},{0,1} };
bool in(int x, int y)
{
	return 0 <= x && x < n && 0 <= y && y < m;
}
struct node
{
	int x, y, d;
	node(int xx, int yy, int dd)
	{
		x = xx;
		y = yy;
		d = dd;
	}
};
int bfs(int sx, int sy)
{
	queue<node>q;
	q.push(node(sx, sy, 0));
	vis[sx][sy] = true;
	while (!q.empty())
	{
		node now = q.front();
		q.pop();
		for (int i = 0; i < 4; i++)
		{
			int tx = now.x + dir[i][0];
			int ty = now.y + dir[i][1];
			if (in(tx, ty) && maze[tx][ty] != '*' && !vis[tx][ty])
			{
				if (maze[tx][ty] == 'T')
				{
					return now.d + 1;
				}
				else
				{
					vis[tx][ty] = true;
					q.push(node(tx, ty, now.d + 1));
				}
			}
		}
	}
	return -1;
}
int main()
{
	cin >> n >> m;
	for (int i = 0; i < n; i++)
	{
		cin >> maze[i];
	}
	int x, y;
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < m; j++)
			if (maze[i][j] == 'S')
			{
				x = i;
				y = j;
			}
	}
	cout << bfs(x, y) << endl;
	return 0;
}

例题2

在一个长度为n的坐标上,小方想从A点移动到B点,他的移动规则为
1.向前一步,坐标增加1;
2.向后一步,坐标减少1.
3.跳跃一步,使得坐标乘2.
小方不能移动到坐标小于0或者大于n的位置
小方想知道从A点移动到B点的最小步数是多少

#include <iostream>
#include <queue>
using namespace std;
queue<pair<int, int>>q;
bool vis[5005];
int main()
{
	int n, A, B,now,step;
	cin >> n >> A >> B;
	q.push(make_pair(A, 0));
	vis[A] = true;
	while (!q.empty())
	{
		now = q.front().first;
		step = q.front().second;
		q.pop();
		if (now == B)
		{
			cout << step << endl;
			break;
		}
		if (now+ 1 <= n&&!vis[now+1])
		{
			q.push(make_pair(now + 1, step + 1));
			vis[now + 1] = true;
		}
		if (now - 1 >= 0 && !vis[now - 1])
		{
			q.push(make_pair(now - 1, step - 1));
			vis[now - 1] = true;
		}
		if (now * 2 <= n && !vis[now * 2])
		{
			q.push(make_pair(now * 2, step + 1));
			vis[now * 2] = true;
		}
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值