📜  门|门CS 2012 |问题 17(1)

📅  最后修改于: 2023-12-03 15:28:49.091000             🧑  作者: Mango

问题介绍

在 ACM/ICPC 门松向祥的 CS 部门 的 2012 年训练赛中,有一道题目叫做“门”。

题目描述:

有一幢 $N\times M$ 的建筑,其中有些位置有门,其余位置为墙。现在需要从左上角走到右下角,并且只能走门连接的位置。求出从左上角到右下角的最短路径长度。

输入格式:

第 1 行两个整数 $N$ 和 $M$,表示建筑的行数和列数。

接下来 $N$ 行,每行 $M$ 个字符,表示该位置的状态。其中 $’.’$ 表示墙,$’#’$ 表示门。

输出格式:

一个整数,表示从左上角到右下角的最短路径长度。如果无法到达,输出 $-1$。

具体例子可以看这里

解题思路

这道题目可以使用 BFS 等算法来解决。具体实现过程可以用一个队列来维护当前可以到达的位置,采用 BFS 进行搜索。对于每个门对应的位置,需要将其所有可以到达的位置入队,并将其 G 值(即距离起点的步数)加一。具体过程如下:

  1. 定义一个队列和一个数组来记录每个位置的 G 值(即距离起点的步数)。
queue<pair<int, int>> q;
int g[N][M];
  1. 将起点入队,并将其 G 值设置为 0。
q.push({0, 0});
g[0][0] = 0;
  1. 如果队列非空,则进行循环操作。从队列中取出队首元素,判断是否为终点。如果是,返回当前步数。否则对其可以到达的位置进行搜索,并更新 G 值。
while (!q.empty()) {
    auto t = q.front();
    q.pop();
    int x = t.first, y = t.second;
    if (x == n - 1 && y == m - 1) return g[x][y];
    for (int i = 0; i < 4; i++) {
        int a = x + dx[i], b = y + dy[i];
        if (a >= 0 && a < n && b >= 0 && b < m && s[a][b] != '#' && g[a][b] == -1) {
            g[a][b] = g[x][y] + 1;
            q.push({a, b});
        }
    }
}
  1. 如果无法到达终点,则返回 $-1$。
return -1;

参考代码

#include <iostream>
#include <cstring>

using namespace std;

const int N = 1e2+10;
const int dx[4] = {-1, 1, 0, 0}, dy[4] = {0, 0, -1, 1};

int n, m;
char s[N][N];
int g[N][N];

int bfs() {
    queue<pair<int, int>> q;
    memset(g, -1, sizeof g);
    q.push({0, 0});
    g[0][0] = 0;
    while (!q.empty()) {
        auto t = q.front();
        q.pop();
        int x = t.first, y = t.second;
        if (x == n - 1 && y == m - 1) return g[x][y];
        for (int i = 0; i < 4; i++) {
            int a = x + dx[i], b = y + dy[i];
            if (a >= 0 && a < n && b >= 0 && b < m && s[a][b] != '#' && g[a][b] == -1) {
                g[a][b] = g[x][y] + 1;
                q.push({a, b});
            }
        }
    }
    return -1;
}

int main() {
    cin >> n >> m;
    for (int i = 0; i < n; i++) cin >> s[i];
    cout << bfs() << endl;
    return 0;
}

以上是本人的程序实现,如果有疑问欢迎交流。