1 条题解

  • 0
    @ 2025-6-16 0:56:03

    解题思路

    此问题的核心在于找出一条路径,使马赫塔吉夫人从家到教堂和从教堂到家时都能使用同一字符串路径,且不经过任何封闭路口。为了解决这个问题,代码采用了双向广度优先搜索(BFS)结合路径验证的方法。

    算法原理

    双向 BFS:从起点(家)和终点(教堂)同时进行 BFS 搜索,这样可以在搜索空间较大的情况下更快地找到相遇点,提高效率。 状态表示:每个状态包含坐标 (x, y)、方向 (dir) 和已走过的路径 (path)。方向用 0-3 表示东、南、西、北。 路径验证:生成路径后,需要验证该路径是否能同时满足从家到教堂和从教堂到家的要求。验证过程模拟机器人按照路径移动,检查是否能正确到达目标点且不经过封闭路口。

    实现步骤

    1.输入处理:读取网格大小、起点和终点坐标,以及封闭路口的位置。

    2.双向 BFS 初始化:分别从起点(面朝东)和终点(面朝西)开始 BFS 搜索,使用队列存储待处理的状态。

    3.状态扩展:对每个状态,尝试四种移动(F、B、L、R),生成新状态并加入队列。检查新状态是否有效(不越界、不经过封闭路口)。

    4.相遇检查:在搜索过程中,检查是否到达目标点或与另一个方向的搜索相遇。若找到路径,进行路径验证。

    5.路径验证:分别模拟从起点到终点和从终点到起点的移动过程,检查路径是否合法。

    c++代码:

    #include <iostream>
    #include <vector>
    #include <queue>
    #include <set>
    #include <utility>
    #include <map> // Replaced unordered_map with map for compatibility
    #include <string>
    using namespace std;
    
    struct State {
        int x, y;
        int dir; // 0: east, 1: south, 2: west, 3: north
        string path;
    };
    
    bool is_valid(int x, int y, int m, int n, const set<pair<int, int> >& closed) {
        pair<int, int> p(x, y);
        return x >= 0 && x < m && y >= 0 && y < n && closed.find(p) == closed.end();
    }
    
    bool is_reversible(const string& path, int m, int n, pair<int, int> start, pair<int, int> end, const set<pair<int, int> >& closed) {
        // Simulate forward (start to end, facing east)
        int x = start.first, y = start.second;
        int dir = 0; // east
    
        for (size_t i = 0; i < path.size(); ++i) {
            char move = path[i];
            if (move == 'F') {
                x += (dir == 0) ? 1 : (dir == 1) ? 0 : (dir == 2) ? -1 : 0;
                y += (dir == 0) ? 0 : (dir == 1) ? -1 : (dir == 2) ? 0 : 1;
            } else if (move == 'B') {
                x -= (dir == 0) ? 1 : (dir == 1) ? 0 : (dir == 2) ? -1 : 0;
                y -= (dir == 0) ? 0 : (dir == 1) ? -1 : (dir == 2) ? 0 : 1;
            } else if (move == 'L') {
                dir = (dir + 3) % 4;
            } else if (move == 'R') {
                dir = (dir + 1) % 4;
            }
    
            if (!is_valid(x, y, m, n, closed)) {
                return false;
            }
        }
    
        if (x != end.first || y != end.second) {
            return false;
        }
    
        // Simulate backward (end to start, facing west)
        x = end.first, y = end.second;
        dir = 2; // west
    
        for (size_t i = 0; i < path.size(); ++i) {
            char move = path[i];
            if (move == 'F') {
                x += (dir == 0) ? 1 : (dir == 1) ? 0 : (dir == 2) ? -1 : 0;
                y += (dir == 0) ? 0 : (dir == 1) ? -1 : (dir == 2) ? 0 : 1;
            } else if (move == 'B') {
                x -= (dir == 0) ? 1 : (dir == 1) ? 0 : (dir == 2) ? -1 : 0;
                y -= (dir == 0) ? 0 : (dir == 1) ? -1 : (dir == 2) ? 0 : 1;
            } else if (move == 'L') {
                dir = (dir + 3) % 4;
            } else if (move == 'R') {
                dir = (dir + 1) % 4;
            }
    
            if (!is_valid(x, y, m, n, closed)) {
                return false;
            }
        }
    
        return x == start.first && y == start.second;
    }
    
    string bidirectional_bfs(int m, int n, pair<int, int> start, pair<int, int> end, const set<pair<int, int> >& closed) {
        queue<State> forward_q, backward_q;
        State init_forward = {start.first, start.second, 0, ""};
        State init_backward = {end.first, end.second, 2, ""};
        forward_q.push(init_forward);
        backward_q.push(init_backward);
    
        map<string, bool> forward_visited, backward_visited;
    
        while (!forward_q.empty() || !backward_q.empty()) {
            if (!forward_q.empty()) {
                State current = forward_q.front();
                forward_q.pop();
    
                if (current.x == end.first && current.y == end.second) {
                    if (is_reversible(current.path, m, n, start, end, closed)) {
                        return current.path;
                    }
                }
    
                if (backward_visited.find(current.path) != backward_visited.end()) {
                    if (is_reversible(current.path, m, n, start, end, closed)) {
                        return current.path;
                    }
                }
    
                forward_visited[current.path] = true;
    
                int dx[] = {1, 0, -1, 0};
                int dy[] = {0, -1, 0, 1};
    
                char moves[] = {'F', 'B', 'L', 'R'};
                for (int i = 0; i < 4; ++i) {
                    char move = moves[i];
                    int new_dir = current.dir;
                    int new_x = current.x;
                    int new_y = current.y;
    
                    if (move == 'F') {
                        new_x += dx[new_dir];
                        new_y += dy[new_dir];
                    } else if (move == 'B') {
                        new_x -= dx[new_dir];
                        new_y -= dy[new_dir];
                    } else if (move == 'L') {
                        new_dir = (new_dir + 3) % 4;
                    } else if (move == 'R') {
                        new_dir = (new_dir + 1) % 4;
                    }
    
                    if (is_valid(new_x, new_y, m, n, closed)) {
                        State next = {new_x, new_y, new_dir, current.path + move};
                        forward_q.push(next);
                    }
                }
            }
    
            if (!backward_q.empty()) {
                State current = backward_q.front();
                backward_q.pop();
    
                if (current.x == start.first && current.y == start.second) {
                    if (is_reversible(current.path, m, n, start, end, closed)) {
                        return current.path;
                    }
                }
    
                if (forward_visited.find(current.path) != forward_visited.end()) {
                    if (is_reversible(current.path, m, n, start, end, closed)) {
                        return current.path;
                    }
                }
    
                backward_visited[current.path] = true;
    
                int dx[] = {1, 0, -1, 0};
                int dy[] = {0, -1, 0, 1};
    
                char moves[] = {'F', 'B', 'L', 'R'};
                for (int i = 0; i < 4; ++i) {
                    char move = moves[i];
                    int new_dir = current.dir;
                    int new_x = current.x;
                    int new_y = current.y;
    
                    if (move == 'F') {
                        new_x += dx[new_dir];
                        new_y += dy[new_dir];
                    } else if (move == 'B') {
                        new_x -= dx[new_dir];
                        new_y -= dy[new_dir];
                    } else if (move == 'L') {
                        new_dir = (new_dir + 3) % 4;
                    } else if (move == 'R') {
                        new_dir = (new_dir + 1) % 4;
                    }
    
                    if (is_valid(new_x, new_y, m, n, closed)) {
                        State next = {new_x, new_y, new_dir, current.path + move};
                        backward_q.push(next);
                    }
                }
            }
        }
    
        return "";
    }
    
    int main() {
        int m, n;
        while (cin >> m >> n && (m != 0 || n != 0)) {
            pair<int, int> start, end;
            cin >> start.first >> start.second >> end.first >> end.second;
    
            int N;
            cin >> N;
            set<pair<int, int> > closed;
            for (int i = 0; i < N; ++i) {
                int x, y;
                cin >> x >> y;
                closed.insert(make_pair(x, y));
            }
    
            string path = bidirectional_bfs(m, n, start, end, closed);
            if (!path.empty()) {
                cout << "YES" << endl;
            } else {
                cout << "NO" << endl;
            }
        }
        return 0;
    }
    • 1

    信息

    ID
    536
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    2
    已通过
    1
    上传者