题意分析
给定一幅字符表示的地图,其中包含有 1 个起点’H’,若干个座位’S’,墙壁’#’和行人’P’。
其中墙壁’#’和行人’P’是不可通过的区域。
假设在地图中,只能沿着上下左右移动,且每移动一个单元格为 1 步。
询问从’H’点出发,是否能够到达两个相邻的’S’,且需要移动的步数最少是多少。
算法分析
从题目当中,我们就可以知道本题需要做什么:
读取字符地图,并找到起点的位置。
从起点开始,遍历该地图,记录到达每一个'S'的距离。
判断是否有两个相邻的'S'都可达,若存在多个解,则需要找到最小的值。
那么我们就按照这三个步骤来解决这道题目。
首先是数据的读入,由于输入数据中已经明确的告诉了我们地图为 N 行 M 列,所以我们只需要一行一行读入字符串,并使用char map[N][M]保存该地图。
map[i][j]表示原地图的第i行第j列的信息。
之后再对整个map[i][j]进行一次 O(mn) 的遍历,找出起点的位置,并记录下来。
我们用startX, startY 来记录起点的坐标。
startX = startY = 0;
// 读入地图
for (int i = 1; i <= N; i++)
scanf(“%s”, map[i] + 1);
// 查找起点H
for (int i = 1; i <= N; i++)
for (int j = 1; j <= M; ++j)
if (map[i][j] == ‘H’) {
startX = i, startY = j;
break;
}
第二步,寻找从起点(startX, startY)分别到每个’S’的最短路径。这一步我们直接使用BFS对整个图进行一次遍历。
首先建立数组int step[N][M],step[i][j]表示从起点到(i,j)的最少步数。
初始化为step[i][j] = INT_MAX,默认为任何点都无法到达。
开始遍历时,将step[ startX ][ startY ]设定为0,并以(startX, startY)开始BFS整个地图。
在遍历整个地图的过程中我们需要注意:
当map[i][j] = '#'或map[i][j] = 'P'时,step[i][j]直接等于INT_MAX,并且不扩展新的节点。
当map[i][j] = 'S'时,我们需要更新当前节点的step[i][j]信息,但是由于当小Hi和小Ho走到位置后就不会再进行移动,所以也不扩展新的节点。
最后当没有新的节点可以到达时,退出BFS,得到整个地图的step[N][M]。
bool inMap(int x, int y) {
// 在地图内 && 不为墙壁同时也不为行人
return (1 <= x && x <= N && 1 <= y && y <= M) && (map[x][y] == ‘.’ || map[x][y] == ‘S’);
}
const int dir[4][2] = { {0, -1}, {1, 0}, {0, 1}, {-1, 0} }; // 方向数组
vector< pair
#include <cstdio>
#include <queue>
#include <algorithm>
using namespace std;
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
char Map[110][110];
int N, M, step[110][110], rec[110][110];
void BFS(int X, int Y) {
queue <pair <int, int> > q;
q.push(make_pair(X, Y));
while(!q.empty()) {
X = q.front().first;
Y = q.front().second;
q.pop();
for (int i = 0; i < 4; i++) {
int x = X + dx[i];
int y = Y + dy[i];
if (x >= 0 && x < N && y >= 0 && y < M && (Map[x][y] == '.' || Map[x][y] == 'S') && !rec[x][y]) {
rec[x][y] = 1;
step[x][y] = step[X][Y] + 1;
if (Map[x][y] == '.') q.push(make_pair(x, y));
}
}
}
}
int main() {
scanf("%d%d", &N, &M);
for (int i = 0; i < N; i++)
scanf("%s", Map[i]);
for (int i = 0; i < N; i++)
for (int j = 0; j < M; j++)
if (Map[i][j] == 'H') BFS(i, j);
int ans = 0x3f3f3f3f;
for (int i = 0; i < N; i++)
for (int j = 0; j < M; j++) if (Map[i][j] == 'S' && step[i][j])
for (int k = 0; k < 4; k++) {
int x = i + dx[k];
int y = j + dy[k];
if (x >= 0 && x < N && y >= 0 && y < M && Map[x][y] == 'S' && step[x][y])
ans = min(ans, step[i][j] + step[x][y]);
}
if (ans != 0x3f3f3f3f)
printf("%d\n", ans);
else
puts("Hi and Ho will not have lunch.");
return 0;
}