题外话-算法-搜索

本人搜索太差了,主要是总结

BFS(Breadth-First-Search),广度优先算法

BFS的思想就是从当前节点扩散到更大的可行的状态上
通常使用队列实现
模版(伪代码)

function BFS(souce) 
  queue Q
  Q.push(souce)
  while(Q != NULL) // 队列不为空
    u = Q.front();
    Q.pop();
    for v is u's neighbor
      if v in low
        Q.push(v)
        ans = .... // 更新答案

还是给道模版题
迷宫寻路
没什么说的,模版

#include<bits/stdc++.h>
using namespace std;
const int M = 100 + 5;
char graph[M][M];
int visited[M][M];
int d[4][2] = {{-1, 0}, {1, 0}, {0, 1}, {0, -1}};
int n, m;
bool BFS(int x, int y) {
	queue<pair<int, int>> Q;
	Q.emplace(x, y);
	visited[x][y] = 1;
	while (!Q.empty()) {
		pair<int, int> u = Q.front();
		Q.pop();
		int x_ = u.first, y_ = u.second;
		for (int i = 0; i < 4; i++) {
			int xx = x_ + d[i][0], yy = y_ + d[i][1];
			if (xx <= n and xx >= 1 and yy <= m and yy >= 1 and !visited[xx][yy] and graph[xx][yy] != '#') {
				Q.emplace(xx, yy);
				visited[xx][yy] = 1;
			}
		}
	}
	return visited[n][m];
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++)
			cin >> graph[i][j];
	if (BFS(1, 1)) 
		cout << "Yes\n";
	else 
		cout << "No\n";
	return 0;
}

变种:0/1BFS

思路和BFS一样,只不过每个点要么是0要么是1,这种情况下,普通的BFS就不行了
其实将queue换成deque就能过了,或者用priority_queue

题目描述
给你一个 \(n \times m\) 的地图,. 是荒地,# 是石头(不能走),数字是国家(编号为 1、2、3),求最少把多少荒地修成路可以使得三个国家连通,无解输出 。
通过填充 .,将 3 个联通块互相联通。
输入格式
第1行:2个整数\(n\), \(m\) 接下来\(n\)行,每行\(m\)个字符,表示地图
输出格式
第1行:1个整数,表示答案。

//在国家上是无损耗的,为0
//而在空地上需要修路,为1
#include <bits/stdc++.h>
using namespace std;
#define Cqbz typedef
Cqbz long long ll;

typedef pair<int, int> PII;
ll n, m;
const int N = 1e3 + 10;
char p[N][N];
int dist[4][N][N];

int dx[] = { 0, 0, 1, -1 };
int dy[] = { 1, -1, 0, 0 };

void bfs(int pos) {
	memset(dist[pos], -1, sizeof dist[pos]);

	deque<PII> q;
	for (int i = 1; i <= n; i++) 
		for (int j = 1; j <= m; j++) 
			if (p[i][j] - '0' == pos) {
				q.push_front({ i, j });
				dist[pos][i][j] = 0;
			}
	while (q.size()) {
		auto t = q.front();
		q.pop_front();
		int x = t.first, y = t.second;
		for (ll i = 0; i < 4; i++) { // 遍历四个方向
			ll a = x + dx[i], b = y + dy[i];
			if (a >= 1 && a <= n && b >= 1 && b <= m && p[a][b] != '#') {
				int w = (p[a][b] == '.' ? 1 : 0);
				if (dist[pos][a][b] == -1) {
					dist[pos][a][b] = dist[pos][x][y] + w;
					if (w) // 权值是否为1
						q.push_back({ a, b });
					else
						q.push_front({ a, b });
				} else if (dist[pos][x][y] + w < dist[pos][a][b])
					dist[pos][a][b] = dist[pos][x][y] + w;
			}
		}
	}
}
int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);

	cin >> n >> m;
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++) cin >> p[i][j];

	bfs(1); //三个国家都遍历,找连通块
	bfs(2);
	bfs(3);

	ll ret = 0x3f3f3f3f3f3f; //结果赋值为极大值

	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			if (p[i][j] == '#')
				continue;
			ll x = dist[1][i][j], y = dist[2][i][j], z = dist[3][i][j];
			if (x == -1 || y == -1 || z == -1)
				continue;
			if (p[i][j] == '.')
				ret = min(ret, x + y + z - 2); // 更新答案,路径被多算了两次
			else
				ret = min(ret, x + y + z);
		}
	}

	if (ret == 0x3f3f3f3f3f3f)
		cout << -1;
	else
		cout << ret;
	return 0;
}
posted @ 2025-07-23 20:44  Yangyihao  阅读(7)  评论(0)    收藏  举报