2021.8.5 BFS典型例题 营救

BFS对于最短路径问题的解决比DFS要快,一般DFS超时问题可以用BFS进行解决。

BFS要用到队列知识,笔者目前还没有深入学习数据结构知识,所以BFS用的不是特别熟练,以营救为例题进行BFS的练习与巩固。

【问题描述】
铁塔尼号遇险了!他发出了求救信号。距离最近的哥伦比亚号收到了讯息,时间就是生命,必须尽快赶到那里。
通过侦测,哥伦比亚号获取了一张海洋图。这张图将海洋部分分化成n*n个比较小的单位,其中用1标明的是陆地,用0标明是海洋。船只能从一个格子,移到相邻的四个格子。
为了尽快赶到出事地点,哥伦比亚号最少需要走多远的距离。
【输入格式】
第一行为n,下面是一个n*n的0、1矩阵,表示海洋地图
最后一行为四个小于n的整数,分别表示哥伦比亚号和铁塔尼号的位置。
【输出格式】
哥伦比亚号到铁塔尼号的最短距离,答案精确到整数。
【输入样例】save.in
3
001
101
100
1 1 3 3
【输出样例】save.out
4
【数据范围】
N<=1000

此题要注意的点:

1.搜索过的点不能重复搜索,搜索完成后将此点标记为“1”,即下次不能再次搜索次点

2.用path数组记录到达每一点的步数,此步数等于到达达到上一点的步数+1

#include<iostream>
#include<queue>
using namespace std;
struct pos {
	int x, y;
};
int ocean[1005][1005], path[1005][1005], n, start_x, start_y, end_x, end_y, ans;//path记录到达各点的步数
int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};
int main(void)
{
	char ch;
	cin >> n;
	for (int y = 1; y <= n; y++)
	{
		for (int x = 1; x <= n; x++)
		{
			cin >> ch;
			if (ch == '1')
				ocean[y][x] = 1;//0代表海洋,1代表陆地
		}
	}
	cin >> start_x >> start_y >> end_x >> end_y;
	ocean[start_y][start_x] = 1;//起点标记为已经遍历过了
	pos p;
	p.x = start_x; p.y = start_y;
	queue<struct pos> qu;//用起点初始化队列
	qu.push(p);
	while (!qu.empty())//empty函数队列为空返回真
	{
		p = qu.front(); qu.pop();//队首元素出队并删除
		if (p.x == end_x && p.y == end_y)//队首元素就是终点则对出循环
		{
			break;
		}
		for (int i = 0; i < 4; i++)//队首元素扩展出4个方向
		{
			int xx = p.x + dx[i];
			int yy = p.y + dy[i];
			if (!ocean[yy][xx] && xx >= 1 && xx <= n && yy >= 1 && yy <= n)
			{
				ocean[yy][xx] = 1;//走过的点标记后以后不能再走了
				path[yy][xx] = path[p.y][p.x] + 1;
				p.x = xx; p.y = yy;
				qu.push(p);//满足条件的点入队
			}
		}
	}
	cout << path[end_y][end_x];
	return 0;
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个基于C++的BFS求最短路径的示例代码: ```cpp #include <iostream> #include <queue> #include <cstring> using namespace std; const int MAXN = 1005; // 最大节点数 const int INF = 0x3f3f3f3f; // 无穷大 int n, m; // n表示节点个数,m表示边数 int dis[MAXN]; // 存储起点到每个节点的距离 bool vis[MAXN]; // 记录每个节点是否被访问过 int head[MAXN], to[MAXN<<1], nxt[MAXN<<1], edge[MAXN<<1], cnt; // 邻接表存图 void addEdge(int u, int v, int w) { to[++cnt] = v; nxt[cnt] = head[u]; edge[cnt] = w; head[u] = cnt; } void bfs(int start) { memset(dis, INF, sizeof(dis)); // 初始化距离为无穷大 memset(vis, false, sizeof(vis)); // 初始化所有节点都未被访问过 dis[start] = 0; // 起点到自己的距离为0 vis[start] = true; // 起点已经访问过了 queue<int> q; // 定义一个队列,用于广度优先搜索 q.push(start); // 将起点加入队列 while (!q.empty()) { int u = q.front(); q.pop(); // 取出队首节点 for (int i = head[u]; i; i = nxt[i]) { int v = to[i], w = edge[i]; if (!vis[v]) { // 如果这个节点未被访问过 dis[v] = dis[u] + w; // 更新距离 vis[v] = true; // 标记为已访问 q.push(v); // 将其加入队列 } } } } int main() { cin >> n >> m; for (int i = 1; i <= m; ++i) { int u, v, w; cin >> u >> v >> w; addEdge(u, v, w); addEdge(v, u, w); // 无向图需要加两条边 } int start; cin >> start; bfs(start); for (int i = 1; i <= n; ++i) { if (dis[i] != INF) { cout << start << " 到 " << i << " 的最短距离为:" << dis[i] << endl; } } return 0; } ``` 这段代码使用邻接表存图,时间复杂度为O(n+m),其中n表示节点数,m表示边数。在实际使用中,可以根据自己的需求进行修改。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值