C++ BFS求最短步数

(一)纯求最短步数

n*n的图,0表示可以走,1表示不能走,求(1, 1)到每个点的最短步数


【Code】
#include <iostream>
#include <queue>
using namespace std;

struct Node {
	int x, y;
	Node(int a=0, int b=0) :x(a), y(b) {}
};
Node node[5001];

bool G[5001][5001];
bool visited[5001][5001];

int dir[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};
int d[5001][5001];
int n;

bool Valid(int x, int y) {
	if(x < 1 || x > n || y < 1 || y > n) return false;
	if(d[x][y] != -1 || G[x][y] == 1) return false;
	return true;
}

void Clear_D() {
	for(int i=1; i<=n; i++)
		for(int j=1; j<=n; j++)
			d[i][j] = -1;
	return;
}

void bfs() {
	queue<Node> Q;
	Q.push(Node(1, 1));
	Clear_D();
	d[1][1] = 0;
	while(!Q.empty()) {
		Node k=Q.front();
		Q.pop();
		for(int i=0; i<4; i++) {
			int next_x = k.x + dir[i][0];
			int next_y = k.y + dir[i][1];
			if(Valid(next_x, next_y)) {
				d[next_x][next_y] = d[k.x][k.y] + 1;
				Q.push(Node(next_x, next_y));
			}
		}
	}

}

int main() {
	cin >> n;
	for(int i=1; i<=n; i++)
		for(int j=1; j<=n; j++)
			cin >> G[i][j];
	bfs();
	for(int i=1; i<=n; i++) {
		for(int j=1; j<=n; j++)
			if(d[i][j] == -1) cout << '-' << ' ';
			else cout << d[i][j] << ' ';
		cout << endl;
	}
	return 0;
}

Input:
5
0 0 1 1 0
0 0 1 1 0
0 0 0 0 0
1 1 1 1 0
1 1 0 0 0



Output:
0 1 - - 8
1 2 - - 7
2 3 4 5 6
- - - - 7
- - 10 9 8


(二)BFS应用

(一)“显示图像”

题目描述

古老的显示屏是由N×M个像素(Pixel)点组成的。一个像素点的位置是根据所在行数和列数决定的。例如P(2,1)表示第2行第1列的像素点。那时候,屏幕只能显示黑与白两种颜色,人们用二进制0和1来表示。0表示黑色,1表示白色。当计算机发出一个指令:P(x,y)=1,则屏幕上的第x行第y列的阴极射线管就开始工作,使该像素点显示白色,若P(x,y)=0,则对应位置的阴极射线管不工作,像素点保持黑色。在某一单位时刻,计算机以N×M二维01矩阵的方式发出显示整个屏幕图像的命令。

例如,屏幕是由3×4的 对应屏幕显示应为:像素点组成,在某单位时刻,计算机发出如下命令:

0001 0011 0110

假设放大后,一个格子表示一个像素点

由于未知的原因,显示黑色的像素点总是受显示白色的像素点的影响——可能是阴极射线管工作的作用。并且,距离越近,影响越大。这里的距离定义如下:设有像素点P1(x1,y1)和像素点P2(x2,y2),则它们之间的距离D(P1,P2):D(P1,P2)=|x1-x2|+|y1-y2| 在某一时刻,计算机发出显示命令后,科学家们期望知道,每个像素点和其最近的显示白色的像素点之间的最短距离是多少——科学家们保证屏幕上至少有一个显示白色的像素点。

上面的例子中,像素P(1,1)与最近的白色像素点之间的距离为3,而像素P(3,2)本身显示白色,所以最短距离为0。

输入输出格式

输入格式:

第一行有两个数字,N和M (1<=N,M<=182),表示屏幕的规格。

以下N行,每行M个数字,0或1。为计算机发出的显示命令。

输出格式:

输出文件有N行,每行M个数字,中间用1个空格分开。第i行第j列的数字表示距像素点P(i,j)最近的白色像素点的最短距离。

输入输出样例

输入样例#1:
3 4
0001
0011
0110
输出样例#1: 
3 2 1 0
2 1 0 0
1 0 0 1





说明

对于30%的数据:N*M<=10000;

对于100%的数据:N*M<=182^2。


样例分析:

第一次:
0 0 1 0
0 1 0 0
1 0 0 1


第二次:
0 2 1 0
2 1 0 0
1 0 0 1


第三次:
3 2 1 0
2 1 0 0
1 0 0 1

【code】BFS
#include <iostream>
#include <queue>
using namespace std;

int n, m;

struct Point {
	int x, y;
	Point(int a=0, int b=0):x(a), y(b) {}
};
#define Valid(x, y) x>=1&&x<=n&&y>=1&&y<=m

char G[201][201];
int d[201][201];

int dir[4][2] = {{1,0}, {0,1}, {-1,0}, {0,-1}};
queue<Point> Q;
bool visited[201][201];

void BFS() {
	while(!Q.empty()) {
		Point k=Q.front();
		Q.pop();
		for(int i=0; i<4; i++) {
			int next_x = k.x + dir[i][0];
			int next_y = k.y + dir[i][1];
			if(Valid(next_x, next_y) && G[next_x][next_y] != '1' && !visited[next_x][next_y]) {
				d[next_x][next_y] = d[k.x][k.y] + 1;
				visited[next_x][next_y] = 1;
				Q.push(Point(next_x, next_y));
			}
		}
	}

}

int main() {
	char c;
	cin >> n >> m;
	for(int i=1; i<=n; i++)
		for(int j=1; j<=m; j++)
			cin >> G[i][j];
	for(int i=1; i<=n; i++)
		for(int j=1; j<=m; j++)
			if(G[i][j] == '1')
				Q.push(Point(i, j));
	BFS();
	for(int i=1; i<=n; i++, cout << endl)
		for(int j=1; j<=m; j++) cout << d[i][j] << ' ';
	return 0;
}




对于迷宫问题路径,可以使用广度优先搜索算法(BFS)来解决。 具体实现步骤如下: 1. 定义一个结构体表示迷宫中的一个点,包含该点的行、列和步数。 ```cpp struct Point { int x, y, step; }; ``` 2. 定义一个队列用于存放待搜索的点。 ```cpp queue<Point> q; ``` 3. 将起点加入队列,并标记为已访问。 ```cpp q.push(Point{start_x, start_y, 0}); visited[start_x][start_y] = true; ``` 4. 循环搜索队列中的点,直到队列为空或者找到终点。 ```cpp while (!q.empty()) { Point cur = q.front(); q.pop(); // 判断是否到达终点 if (cur.x == end_x && cur.y == end_y) { return cur.step; } // 向四个方向扩展 for (int i = 0; i < 4; ++i) { int next_x = cur.x + dx[i]; int next_y = cur.y + dy[i]; // 判断是否越界或者已访问 if (next_x < 0 || next_x >= n || next_y < 0 || next_y >= m || visited[next_x][next_y]) { continue; } // 判断是否可以通过 if (maze[next_x][next_y] == '.') { q.push(Point{next_x, next_y, cur.step + 1}); visited[next_x][next_y] = true; } } } ``` 完整代码: ```cpp #include <iostream> #include <queue> #include <cstring> using namespace std; const int MAXN = 1005; struct Point { int x, y, step; }; int n, m; int start_x, start_y, end_x, end_y; char maze[MAXN][MAXN]; bool visited[MAXN][MAXN]; int dx[] = {-1, 0, 1, 0}; int dy[] = {0, 1, 0, -1}; int bfs() { queue<Point> q; q.push(Point{start_x, start_y, 0}); visited[start_x][start_y] = true; while (!q.empty()) { Point cur = q.front(); q.pop(); // 判断是否到达终点 if (cur.x == end_x && cur.y == end_y) { return cur.step; } // 向四个方向扩展 for (int i = 0; i < 4; ++i) { int next_x = cur.x + dx[i]; int next_y = cur.y + dy[i]; // 判断是否越界或者已访问 if (next_x < 0 || next_x >= n || next_y < 0 || next_y >= m || visited[next_x][next_y]) { continue; } // 判断是否可以通过 if (maze[next_x][next_y] == '.') { q.push(Point{next_x, next_y, cur.step + 1}); visited[next_x][next_y] = true; } } } // 无法到达终点 return -1; } int main() { cin >> n >> m; for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { cin >> maze[i][j]; if (maze[i][j] == 'S') { start_x = i; start_y = j; } else if (maze[i][j] == 'E') { end_x = i; end_y = j; } } } int ans = bfs(); if (ans == -1) { cout << "Can't reach the end point!" << endl; } else { cout << ans << endl; } return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值