题外话-算法-搜索
本人搜索太差了,主要是总结
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;
}

浙公网安备 33010602011771号