原题目链接:Link
题目描述
某个国家的地图可以看做是一个n*m的表格,单元格为’#‘表示城市区域,单元格为’.‘表示耕地区域。连通的’#'表示的区域是同一个城市。从一个单元格走到上下左右相邻的另一个单元格为一步。现在,你可以选择在任何一个城市的任何一个单元格中,请问你要走到其他的城市中去,最少要走多少步?
输入格式
第一行两个整数n和m。(1<=n,m<=500)
接下来有n行,每行一个字符串,有m个字符,每个字符要么是’#’,要么是’.’。
保证地图中至少有两个城市。
输出格式
最近两个城市的距离。
样例
样例输入
4 4
##…
…#
#…
…
样例输出
2
分析:
用两重循环遍历数组,每遇到一个‘#‘,就用dfs搜索,把它所在城市的所有’#‘变成’A’,顺便将这些位置入队列。再用bfs搜索,找到从当前位置到下一个城市的最短路。循环完之后,所有城市、所有路径都搜索完了。
需要特别注意细节的处理。
代码:
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
const int Maxn = 5e2 + 5;
const int zx[4] = {-1, 0, 1, 0}, zy[4] = {0, 1, 0, -1};
int n, m, ans = 1e6;
char c[Maxn][Maxn];
bool vis[Maxn][Maxn];
struct node {
int x, y, step;
};
queue<node> q;
void dfs(int x, int y) {
c[x][y] = 'A';
q.push((node){x, y, 0});
for(int i = 0;i < 4; ++i) {
int dx = x + zx[i], dy = y + zy[i];
if(dx >= 1 and dy >= 1 and dx <= n and dy <= m and c[dx][dy] == '#') dfs(dx, dy);
}
}
void bfs() {
memset(vis, 0, sizeof(vis));
while(!q.empty()) {
node p = q.front();
q.pop();
if(c[p.x][p.y] == '#') {
ans = min(ans, p.step);
while(!q.empty()) q.pop(); // 清空当前队列,不写89分
return ;
}
for(int i = 0;i < 4; ++i) {
int dx = p.x + zx[i], dy = p.y + zy[i];
if(dx >= 1 and dy >= 1 and dx <= n and dy <= m and !vis[dx][dy] and c[dx][dy] != 'A') {
vis[dx][dy] = 1;
q.push((node){dx, dy, p.step + 1});
}
}
}
}
int main() {
scanf("%d %d", &n, &m);
for(int i = 1;i <= n; ++i) scanf("%s", c[i] + 1);
for(int i = 1;i <= n; ++i)
for(int j = 1;j <= m; ++j) {
if(c[i][j] == '#') {
dfs(i, j);
bfs();
}
}
printf("%d", ans);
return 0;
}