信息学奥赛一本通之基础算法——第八章 广度优先搜索算

14 篇文章 0 订阅
3 篇文章 0 订阅

链接索引🔗:

第八章 广度优先搜索算

全部都是用队列(queue)来做,超方便!!!

1329:【例8.2】细胞

请添加图片描述

#include <bits/stdc++.h>
using namespace std;

struct Node{
	int x, y;
};

void bfs(int s1, int s2, int n, int m, vector<vector<int>>& a, vector<vector<bool>>& v){
	static const int fx[4] = {-1, 1, 0, 0};
	static const int fy[4] = {0, 0, -1, 1};
	queue<Node> q;
	q.push({s1, s2});
	v[s1][s2] = true;
	while (!q.empty()){
		Node c = q.front();
		q.pop();
		for (int i = 0; i < 4; i++){
			int tx = c.x + fx[i];
			int ty = c.y + fy[i];
			if (tx >= 0 && tx < n && ty >= 0 && ty < m && a[tx][ty] != 0 && !v[tx][ty]){
				v[tx][ty] = true;
				q.push({tx, ty});
			}
		}
	}
}

int cnt(int n, int m, vector<vector<int>>& a){
	vector<vector<bool>> v;
	v.resize(n, vector<bool>(m, false));
	int sum = 0;
	for (int i = 0; i < n; i++){
		for (int j = 0; j < m; j++){
			if (a[i][j] != 0 && !v[i][j]){
				bfs(i, j, n, m, a, v);
				sum++;
			}
		}
	}
	return sum;
}

int main(){
	int n, m;
	cin >> n >> m;
	vector<vector<int>> a;
	a.resize(n, vector<int> (m));
	for (int i = 0; i < n; i++){
		for (int j = 0; j < m; j++){
			char c;
			cin >> c;
			a[i][j] = c - '0';
		}
	}
	cout << cnt(n, m, a) << endl;
	return 0;
}

1330:【例8.3】最少步数

请添加图片描述

#include <bits/stdc++.h>
using namespace std;

struct Node {
    int x, y, dist;
};

int bfs(int s, int e) {
	static const int fx[12] = {-1, -2, -2, -1, 1, 2, 2, 1, -2, -2, 2, 2};
	static const int fy[12] = {-2, -1, 1, 2, 2, 1, -1, -2, 2, -2, -2, 2};
    vector<vector<bool>> v;
    v.resize(110, vector<bool>(110, false));
    queue<Node> q;
    q.push({s, e, 0});
    v[s][e] = true;
    while (!q.empty()) {
        Node cur = q.front();
        q.pop();
        if (cur.x == 1 && cur.y == 1) {
            return cur.dist;
        }
        for (int i = 0; i < 12; i++) {
            int tx = cur.x + fx[i];
            int ty = cur.y + fy[i];
            if (tx >= 1 && tx <= 100 && ty >= 1 && ty <= 100 && !v[tx][ty]) {
                v[tx][ty] = true;
                q.push({tx, ty, cur.dist + 1});
            }
        }
    }
    return -1;
}

int main() {
    int ax, ay, bx, by;
    cin >> ax >> ay >> bx >> by;
    cout << bfs(ax, ay) << endl;
    cout << bfs(bx, by) << endl;
    return 0;
}

1248:Dungeon Master

请添加图片描述

#include <iostream>
#include <vector>
#include <queue>
using namespace std;

struct Node {
    int x, y, z, s;
};

int bfs(const vector<vector<string>>& a, int l, int r, int c) {
    static const int fx[6] = {-1, 1, 0, 0, 0, 0};
    static const int fy[6] = {0, 0, -1, 1, 0, 0};
    static const int fz[6] = {0, 0, 0, 0, -1, 1};
    vector<vector<vector<bool>>> vis(l, vector<vector<bool>>(r, vector<bool>(c, false)));
    queue<Node> q;
    for (int i = 0; i < l; i++) {
        for (int j = 0; j < r; j++) {
            for (int k = 0; k < c; k++) {
                if (a[i][j][k] == 'S') {
                    q.push({i, j, k, 0}); 
                    vis[i][j][k] = true; 
                    break;
                }
            }
        }
    }
    while (!q.empty()) {
        Node current = q.front();
        q.pop();
        if (a[current.x][current.y][current.z] == 'E') {
            return current.s; 
        }
        for (int i = 0; i < 6; ++i) {
            int tx = current.x + fx[i];
            int ty = current.y + fy[i];
            int tz = current.z + fz[i];
            if (tx >= 0 && tx < l && ty >= 0 && ty < r && tz >= 0 && tz < c && !vis[tx][ty][tz] && a[tx][ty][tz] != '#') {
                vis[tx][ty][tz] = true;
                q.push({tx, ty, tz, current.s + 1});
            }
        }
    }
    return -1; 
}

int main() {
    int l, r, c;
    while (cin >> l >> r >> c && (l || r || c)) {
        vector<vector<string>> a;
        a.resize(l, vector<string>(r));
        for (int i = 0; i < l; ++i) {
            for (int j = 0; j < r; ++j) {
                cin >> a[i][j];
            }
        }
        int result = bfs(a, l, r, c);
        if (result != -1) {
            cout << "Escaped in " << result << " minute(s)." << endl;
        } else {
            cout << "Trapped!" << endl;
        }
    }
    return 0;
}

1249:Lake Counting

记住这里的方向数组要定义 8 个哟!因为是数池塘(八方向)——不折不扣的宽度优先搜索的经典问题

请添加图片描述

#include <bits/stdc++.h>
using namespace std;

int n, m; 

struct Node {
    int x, y;
};

int fx[8] = {-1, -1, -1, 0, 0, 1, 1, 1};
int fy[8] = {-1, 0, 1, -1, 1, -1, 0, 1};

void bfs(vector<vector<char>>& l, int x, int y) {
    queue<Node> q;
    q.push({x, y});
    l[x][y] = '.'; 
    while (!q.empty()) {
        Node cur = q.front();
        q.pop();
        for (int i = 0; i < 8; i++) {
            int tx = cur.x + fx[i], ty = cur.y + fy[i];
            if (tx >= 0 && tx < n && ty >= 0 && ty < m && l[tx][ty] == 'W') {
                l[tx][ty] = '.';
                q.push({tx, ty});
            }
        }
    }
}

int main() {
    cin >> n >> m;
    vector<vector<char>> l(n, vector<char>(m));
    for (int i = 0; i < n; i++){
     for (int j = 0; j < m; j++){
      cin >> l[i][j];
     }
    }
    int p = 0;
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            if (l[i][j] == 'W') {
                bfs(l, i, j); 
                p++; 
            }
        }
    }
    cout << p << endl; 
    return 0;
}

1250:The Castle

这一道题我认为是比较复杂的

请添加图片描述

#include <iostream>
#include <vector>
#include <queue>
using namespace std;

vector<vector<int>> c(50, vector<int>(50));
vector<vector<bool>> v(50, vector<bool>(50, false));
int m, n;

int fx[4] = {-1, 0, 1, 0};
int fy[4] = {0, 1, 0, -1};
int w[4] = {2, 4, 8, 1};

int bfs(int x, int y) {
    queue<pair<int, int>> q;
    q.push({x, y});
    v[x][y] = true;
    int a = 0;
    while (!q.empty()) {
        int x1 = q.front().first;
        int y1 = q.front().second;
        q.pop();
        a++;
        for (int i = 0; i < 4; i++) {
            int tx = x1 + fx[i];
            int ty = y1 + fy[i];
            if (tx >= 0 && tx < m && ty >= 0 && ty < n && !v[tx][ty] && (c[x1][y1] & w[i]) == 0) {
                v[tx][ty] = true;
                q.push({tx, ty});
            }
        }
    }
    return a;
}

int main() {
    cin >> m >> n;
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            cin >> c[i][j];
        }
    }
    int r = 0, ma = 0;
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            if (!v[i][j]) {
                r++;
                ma = max(ma, bfs(i, j));
            }
        }
    }
    cout << r << endl << ma << endl;
    return 0;
}

1251:仙岛求药

请添加图片描述

#include <bits/stdc++.h>
using namespace std;

char a[25][25];
int m, n;
int fx[4] = {0, 1, 0, -1};
int fy[4] = {1, 0, -1, 0};

struct Node{
	int x, y, step;
};

int bfs(int s1, int s2, int e1, int e2)
{
	queue<Node> q;
	q.push({s1, s2, 0});
	a[s1][s2] = '#';
	while (!q.empty())
	{
		Node current = q.front();
		q.pop();
		if (current.x == e1 && current.y == e2)
		{
			return current.step;
		}
		for (int i = 0; i < 4; i++)
		{
			int tx = current.x + fx[i];
			int ty = current.y + fy[i];
			if (a[tx][ty] == '.' || a[tx][ty] == '*')
			{
				a[tx][ty] = '#';
				q.push({tx, ty, current.step + 1});
			}
		}
	}
	return -1;
}

int main()
{
	while (cin >> m >> n)
	{
		int s1, s2, e1, e2;
		memset(a, 0, sizeof(a));
		if (m == 0 && n == 0)
		{
			break;
		}
		for (int i = 1; i <= m; i++)
		{
			for (int j = 1; j <= n; j++)
			{
				cin >> a[i][j];
				if (a[i][j] == '@')
				{
					s1 = i;
					s2 = j;
				}
				if (a[i][j] == '*')
				{
					e1 = i;
					e2 = j;
				}
			}
		}
		cout << bfs(s1, s2, e1, e2) << endl;
	}
	return 0;
}

1252:走迷宫

请添加图片描述

#include <iostream>
#include <vector>
#include <queue>
using namespace std;

struct Node {
    int x, y, step;
};

// 方向数组,表示上、下、左、右四个方向的移动
int dx[4] = {-1, 1, 0, 0};
int dy[4] = {0, 0, -1, 1};

int bfs(const vector<vector<char>>& maze, int R, int C) {
    vector<vector<bool>> visited(R, vector<bool>(C, false)); // 访问状态数组
    queue<Node> q;
    q.push({0, 0, 1}); // 从左上角开始,步数为1(包括起点)
    visited[0][0] = true;

    while (!q.empty()) {
        Node current = q.front();
        q.pop();

        // 到达右下角
        if (current.x == R - 1 && current.y == C - 1) {
            return current.step;
        }

        // 尝试四个方向的移动
        for (int i = 0; i < 4; ++i) {
            int nx = current.x + dx[i];
            int ny = current.y + dy[i];
            if (nx >= 0 && nx < R && ny >= 0 && ny < C && !visited[nx][ny] && maze[nx][ny] == '.') {
                visited[nx][ny] = true;
                q.push({nx, ny, current.step + 1});
            }
        }
    }

    return -1; // 如果无法到达终点(虽然题目保证可以到达)
}

int main() {
    int R, C;
    cin >> R >> C;
    vector<vector<char>> maze(R, vector<char>(C));
    for (int i = 0; i < R; ++i) {
        for (int j = 0; j < C; ++j) {
            cin >> maze[i][j];
        }
    }

    cout << bfs(maze, R, C) << endl;
    return 0;
}
#include <iostream>
#include <vector>
#include <queue>
using namespace std;

struct Node {
    int x, y, step;
};

int fx[4] = {-1, 1, 0, 0};
int fy[4] = {0, 0, -1, 1};

int bfs(const vector<vector<char>>& a, int r, int c) {
    vector<vector<bool>> v(r, vector<bool>(c, false));
    queue<Node> q;
    q.push({0, 0, 1});
    v[0][0] = true;
    while (!q.empty()) {
        Node current = q.front();
        q.pop();
        if (current.x == r - 1 && current.y == c - 1) {
            return current.step;
        }
        for (int i = 0; i < 4; i++) {
            int tx = current.x + fx[i];
            int ty = current.y + fy[i];
            if (tx >= 0 && tx < r && ty >= 0 && ty < c && !v[tx][ty] && a[tx][ty] == '.') {
                v[tx][ty] = true;
                q.push({tx, ty, current.step + 1});
            }
        }
    }
    return -1;
}

int main() {
    int r, c;
    cin >> r >> c;
    vector<vector<char>> a;
    a.resize(r, vector<char>(c));
    for (int i = 0; i < r; i++) {
        for (int j = 0; j < c; j++) {
            cin >> a[i][j];
        }
    }

    cout << bfs(a, r, c) << endl;
    return 0;
}

1253:抓住那头牛

请添加图片描述

#include <iostream>
#include <queue>
#include <vector>
using namespace std;

const int MAX = 100001; // 数轴的最大范围

int bfs(int N, int K) {
    vector<int> visited(MAX, 0); // 访问数组,同时记录到达每个位置的最短时间
    queue<int> q;
    q.push(N); // 将起始位置入队
    visited[N] = 1; // 标记起始位置已访问,初始化为1而不是0,用于避免特殊情况N=0

    while (!q.empty()) {
        int current = q.front();
        q.pop();

        // 如果当前位置就是牛的位置,返回当前已经花费的时间
        if (current == K) {
            return visited[current] - 1; // 返回结果时减去初始的1
        }

        // 尝试三种移动方式
        int nextPos = current - 1;
        if (nextPos >= 0 && !visited[nextPos]) {
            visited[nextPos] = visited[current] + 1;
            q.push(nextPos);
        }

        nextPos = current + 1;
        if (nextPos < MAX && !visited[nextPos]) {
            visited[nextPos] = visited[current] + 1;
            q.push(nextPos);
        }

        nextPos = current * 2;
        if (nextPos < MAX && !visited[nextPos]) {
            visited[nextPos] = visited[current] + 1;
            q.push(nextPos);
        }
    }

    return -1; // 如果没有找到路径,返回-1(理论上不会发生,因为题目保证了解的存在)
}

int main() {
    int N, K;
    cin >> N >> K;
    cout << bfs(N, K) << endl;
    return 0;
}
#include <bits/stdc++.h>
using namespace std;

const int MAX_SIZE = 1e5 + 100;
vector<bool> vis(MAX_SIZE);

struct Node{
	int x, step;
};

int bfs(int n, int k)
{
	queue<Node> q;
	q.push({n, 0});
	vis[n] = true;
	while (!q.empty())
	{
		Node current = q.front();
		q.pop();
		if (current.x == k)
		{
			return current.step;
		}
		for (int i = 0; i < 3; ++i)
		{
			int tx;
			if (i == 0) tx = current.x - 1;
			if (i == 1) tx = current.x + 1;
			if (i == 2) tx = current.x * 2;
			if (tx >= 0 && tx < 100000 && vis[tx] == false)
			{
				vis[tx] = true;
				q.push({tx, current.step + 1});
			}
		}
	}
	return -1;
}

int main()
{
	int n, k;
	cin >> n >> k;
	if (n == k)
	{
		cout << 0 << endl;
	}
	else 
	{
		cout << bfs(n, k) << endl;
	}
	return 0;
}
#include <bits/stdc++.h>
using namespace std;

int q[100001][3], a[100001], head = 0, tail = 1, n, k, t, xx;
int main()
{
	cin >> n >> k;
	if (n == k)
	{
		cout << 0 << endl;
		return 0;
	}
	q[1][0] = n;
	q[1][1] = 0;
	a[n] = 1;
	while (head <= tail)
	{
		head++;
		xx = q[head][0];
		for (int i = 1; i <= 3; i++)
		{
			if (i == 1) t = xx + 1;
			if (i == 2) t = xx - 1;
			if (i == 3) t = 2 * xx;
			if (t >= 0 && t <= 100000 && a[t] == 0)
			{
				tail++;
				q[tail][0] = t;
				q[tail][1] = q[head][1] + 1;
				a[t] = 1;
				if (t == k)
				{
					cout << q[tail][1] << endl;
					return 0;
				}
			}
		}
	}
	return 0;
}

1254:走出迷宫

请添加图片描述

第八章中最简单的一道题!!!

#include <iostream>
#include <vector>
#include <queue>
using namespace std;

const int MAXN = 100;
vector<vector<char>> maze;
vector<vector<bool>> visited;
int dx[4] = {0, 0, -1, 1}; // 上下左右移动
int dy[4] = {-1, 1, 0, 0};
int n, m; // 迷宫的行数和列数

struct Node {
    int x, y, step;
};

int bfs(int sx, int sy, int ex, int ey) {
    queue<Node> q;
    q.push({sx, sy, 0});
    visited[sx][sy] = true;
    
    while (!q.empty()) {
        Node current = q.front();
        q.pop();
        
        if (current.x == ex && current.y == ey) {
            return current.step;
        }
        
        for (int i = 0; i < 4; ++i) {
            int nx = current.x + dx[i];
            int ny = current.y + dy[i];
            
            if (nx >= 0 && nx < n && ny >= 0 && ny < m && !visited[nx][ny] && maze[nx][ny] != '#') {
                visited[nx][ny] = true;
                q.push({nx, ny, current.step + 1});
            }
        }
    }
    
    return -1; // 如果没有路径可以到达
}

int main() {
    cin >> n >> m;
    maze.resize(n, vector<char>(m)); // 使用resize为迷宫分配空间
    visited.resize(n, vector<bool>(m, false)); // 同样为访问状态分配空间
    int sx, sy, ex, ey; // 起点和终点坐标
    
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            cin >> maze[i][j];
            if (maze[i][j] == 'S') {
                sx = i;
                sy = j;
            }
            if (maze[i][j] == 'T') {
                ex = i;
                ey = j;
            }
        }
    }
    
    cout << bfs(sx, sy, ex, ey) << endl;
    return 0;
}
#include <bits/stdc++.h>
using namespace std;

int n, m;
char a[200][200];
int fx[4] = {0, 1, 0, -1};
int fy[4] = {1, 0, -1, 0};

struct Node{
	int x, y, dist;
};

int bfs(int s1, int s2, int e1, int e2)
{
	queue<Node> q;
	q.push({s1, s2, 0});
	while (!q.empty())
	{
		Node current = q.front();
		q.pop();
		if (current.x == e1 && current.y == e2)
		{
			return current.dist;
		}
		for (int i = 0; i < 4; i++)
		{
			int tx = current.x + fx[i];
			int ty = current.y + fy[i];
			if (tx >= 1 && tx <= n && ty >= 1 && ty <= m && (a[tx][ty] == '.' || a[tx][ty] == 'T'))
			{
				a[tx][ty] = '#';
				q.push({tx, ty, current.dist + 1});
			}
		}
	}
}

int main()
{
	int s1, s2, e1, e2;
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= m; j++)
		{
			cin >> a[i][j];
			if (a[i][j] == 'S')
			{
				s1 = i;
				s2 = j;
			}
			if (a[i][j] == 'T')
			{
				e1 = i;
				e2 = j;
			}
		}
	}
	cout << bfs(s1, s2, e1, e2) << endl;
	return 0;
}

1255:迷宫问题

请添加图片描述

#include<iostream>
#include<queue>
using namespace std;

const int N = 5;
struct Node {
	int x, y;
};

queue<Node> q;
Node pre[N][N];
int g[N][N], dir[4][2] = { -1,0,0,1,1,0,0,-1 };
bool st[N][N];
// 将(x,y)入队并标记,记录(x,y)的前驱是(tx,ty)
void push(int x, int y, int tx, int ty) {
	Node node = { x,y };
	q.push(node);
	st[x][y] = true;
	pre[x][y].x = tx;
	pre[x][y].y = ty;
 
}
void print(int x, int y) {   
	if (x == -1 && y == -1) return;
	print(pre[x][y].x, pre[x][y].y);
	cout << "(" << x << ", " << y << ")" << endl;
}
void bfs() {
	push(0, 0, -1, -1);   
	while (q.size()) {
		Node t = q.front();
		q.pop();
		if (t.x == 4 && t.y == 4) {
			print(4, 4);
			break;
		}
		for (int i = 0; i < 4; i++) {
			int nx = t.x + dir[i][0], ny = t.y + dir[i][1];
			if (nx >= 0 && nx < 5 && ny >= 0 && ny < 5 && g[nx][ny] == 0 && !st[nx][ny]) push(nx, ny, t.x, t.y);
		}
	}
}
int main() {
	for (int i = 0; i < N; i++)
		for (int j = 0; j < N; j++) cin >> g[i][j];
	bfs();
	return 0;
}

这段代码是参考哪一位博主的我忘记了,如果知道的话,就留言

1256:献给阿尔吉侬的花束

请添加图片描述

#include <iostream>
#include <vector>
#include <queue>
using namespace std;

struct Node {
    int x, y, dist;
};

vector<vector<char>> a;

int fx[4] = {1, -1, 0, 0};
int fy[4] = {0, 0, 1, -1};

int bfs(int s1, int s2, int e1, int e2);

int main() {
    int t;
    cin >> t;
    for (int k = 0; k < t; k++) {
        int r, c;
        cin >> r >> c;
        a.clear();
        a.resize(r, vector<char>(c));

        int s1, s2, e1, e2;
        for (int i = 0; i < r; i++) {
            for (int j = 0; j < c; j++) {
                cin >> a[i][j];
                if (a[i][j] == 'S') {
                    s1 = i;
                    s2 = j;
                }
                if (a[i][j] == 'E') {
                    e1 = i;
                    e2 = j;
                }
            }
        }

        int ans = bfs(s1, s2, e1, e2);
        if (ans == -1) {
            cout << "oop!" << endl;
        } else {
            cout << ans << endl;
        }
    }
    return 0;
}

int bfs(int s1, int s2, int e1, int e2) {
    queue<Node> q;
    q.push({s1, s2, 0});
    a[s1][s2] = '#';
    while (!q.empty()) {
        Node current = q.front();
        q.pop();
        if (current.x == e1 && current.y == e2) {
            return current.dist;
        }
        int tx, ty;
        for (int i = 0; i < 4; i++) {
            tx = current.x + fx[i];
            ty = current.y + fy[i];
            if (tx >= 0 && tx < a.size() && ty >= 0 && ty < a[0].size() && (a[tx][ty] == '.' || a[tx][ty] == 'E')) {
                a[tx][ty] = '#';
                q.push({tx, ty, current.dist + 1});
            }
        }
    }
    return -1;
}

1257:Knight Moves

请添加图片描述

#include <iostream>
#include <vector>
#include <queue>
using namespace std;

struct Position {
    int x, y, step;
};

// 马的8种可能移动
int dx[8] = {-2, -2, -1, -1, 1, 1, 2, 2};
int dy[8] = {-1, 1, -2, 2, -2, 2, -1, 1};

int bfs(int L, int sx, int sy, int ex, int ey) {
    vector<vector<bool>> visited(L, vector<bool>(L, false));
    queue<Position> q;
    q.push({sx, sy, 0});
    visited[sx][sy] = true;

    while (!q.empty()) {
        Position current = q.front();
        q.pop();

        if (current.x == ex && current.y == ey) {
            return current.step;
        }

        for (int i = 0; i < 8; ++i) {
            int nx = current.x + dx[i];
            int ny = current.y + dy[i];

            if (nx >= 0 && nx < L && ny >= 0 && ny < L && !visited[nx][ny]) {
                visited[nx][ny] = true;
                q.push({nx, ny, current.step + 1});
            }
        }
    }

    return -1; // 这种情况理论上不会发生,因为题目保证了解的存在
}

int main() {
    int t;
    cin >> t;
    while (t--) {
        int L, sx, sy, ex, ey;
        cin >> L >> sx >> sy >> ex >> ey;
        cout << bfs(L, sx, sy, ex, ey) << endl;
    }
    return 0;
}

完结撒花!!!!!

| 🌸 |
🌸 | 🌸 |
| 🌸 | | 🌸 |
🌸 | 🌸 |
| 🌸 |
| 🌸 |
🌸 | 🌸 |
| 🌸 | | 🌸 |
🌸 | 🌸 |
| 🌸 |

  • 13
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值