CSES 1194 多源 BFS

题目You are given a map of a labyrinth, and your task is to find a path from start to end. You can walk left, right, up and down.
Input
The first input line has two integers n and m: the height and width of the map.
Then there are n lines of m characters describing the labyrinth. Each character is . (floor), # (wall), A (start), or B (end). There is exactly one A and one B in the input.
Output
First print "YES", if there is a path, and "NO" otherwise.
If there is a path, print the length of the shortest such path and its description as a string consisting of characters L (left), R (right), U (up), and D (down). You can print any valid solution.
Constraints

1 \le n,m \le 1000

Example
Input:
5 8
########

.A#...#

.##.#B#

......#

########

Output:
YES
9
LDDRRRRRU

这道题考查多元BFS,顾名思义在寻找最短路径的同时,不止一个对象,本题主要是m和p的一个最短路径追赶问题
关键代码如下
分为两个BFS函数来写
第一个先写monster的

点击查看代码
void BFS_m(){
    Node queue[MAXN * MAXN];
    int front = 0, rear = 0;
    memset(visited_m, 0, sizeof(visited_m));
    memset(monster, 0x3f, sizeof(monster));
//找到怪物的位置
    for (int y = 0; y < n; y++) {
        for (int x = 0; x < m; x++) {
            if (map[y][x] == 'M') {
                monster[y][x] = 0;
                queue[rear++] = (Node){x, y, 0};
            }
        }
    }
    while(front < rear){
        Node now = queue[front++];
        for(int d = 0; d < 4; d++){
            int nx = now.x + dx[d];
            int ny = now.y + dy[d];

            if(!visited_m[ny][nx] &&
            nx >= 0 && nx < n && ny >= 0 && ny < m &&
            map[ny][nx] != '#' ){
                visited_p[ny][nx] = 1;
                monster[ny][nx] = now.step + 1;
                queue[rear++] = (Node){nx, ny, now.step + 1};
            }
        }
    }
}
这段多了一句` memset(monster, 0x3f, sizeof(monster));`意义是初始化monser的时间,也就是判断能不能追上,是否monster的最短路径更快的判读 因此在player的BFS函数中
点击查看代码
int BFS_p(int sx, int sy) {
    Node queue[MAXN * MAXN];
    int front = 0, rear = 0;
    memset(visited_p, 0, sizeof(visited_p));
    queue[rear++] = (Node){sx, sy, 0};
    visited_p[sy][sx] = 1;

    while (front < rear) {
        Node now = queue[front++];

        // 如果到达边界,就可以逃生
        if (now.x == 0 || now.x == m - 1 || now.y == 0 || now.y == n - 1) {
            ex = now.x;
            ey = now.y;
            return 1;
        }

        for (int d = 0; d < 4; d++) {
            int nx = now.x + dx[d];
            int ny = now.y + dy[d];

            if(!visited_p[ny][nx] &&
            nx >= 0 && nx < n && ny >= 0 && ny < m &&
            map[ny][nx] != '#' && now.step + 1 < monster[ny][nx]){
            visited_p[ny][nx] = 1;
            prev_dir[ny][nx] = dirChar[d];
            queue[rear++] = (Node){nx, ny, now.step + 1};
            }
        }
    }
    return  0;
}
关键在于` now.step + 1 < monster[ny][nx]`这一句判断,在满足不越界,访问最短的同时还不能被monster赶上

后面就是回溯整个路径

点击查看代码
int printPath(int sx, int sy, int ex, int ey) {  //记录并输出路径
    char path[MAXN * MAXN];
    int len = 0;
    int x = ex,y = ey;
    while (!(x == sx && y == sy)){
        char d = prev_dir[y][x]; //从哪个方向走过来的
        path[len++] = d;
        if (d == 'U')
            y += 1;
        else if (d == 'D')
            y -= 1;
        else if (d == 'L')
            x += 1;
        else if (d == 'R')
            x -= 1;

    }
    for (int i = 0; i < len / 2; ++i) {//路径反转
        swap(&path[i], &path[len - 1 - i]);
    }
    printf("YES\n");
    printf("%d\n %s\n",len ,path);
}

完整代码如下

点击查看代码
#include <stdio.h>
#include <string.h>

#define MAXN 1002

typedef struct {
    int x, y, step;
} Node;

int n,m;
int ex, ey;
char map[MAXN][MAXN];
int monster[MAXN][MAXN];
int visited_p[MAXN][MAXN];
int visited_m[MAXN][MAXN];
char prev_dir[MAXN][MAXN];


int dx[4] = {0, 0, -1, 1};     // 上下左右移动
int dy[4] = {-1, 1, 0, 0};
char dirChar[4] = {'U', 'D', 'L', 'R'}; // 移动对应的方向字符

void swap(char* x, char* y){
    char temp = *x;
    *x = *y;
    *y = temp;
}

void BFS_m(){
    Node queue[MAXN * MAXN];
    int front = 0, rear = 0;
    memset(visited_m, 0, sizeof(visited_m));
    memset(monster, 0x3f, sizeof(monster));
//找到怪物的位置
    for (int y = 0; y < n; y++) {
        for (int x = 0; x < m; x++) {
            if (map[y][x] == 'M') {
                monster[y][x] = 0;
                queue[rear++] = (Node){x, y, 0};
            }
        }
    }
    while(front < rear){
        Node now = queue[front++];
        for(int d = 0; d < 4; d++){
            int nx = now.x + dx[d];
            int ny = now.y + dy[d];

            if(!visited_m[ny][nx] &&
            nx >= 0 && nx < n && ny >= 0 && ny < m &&
            map[ny][nx] != '#' ){
                visited_p[ny][nx] = 1;
                monster[ny][nx] = now.step + 1;
                queue[rear++] = (Node){nx, ny, now.step + 1};
            }
        }
    }
}

int BFS_p(int sx, int sy) {
    Node queue[MAXN * MAXN];
    int front = 0, rear = 0;
    memset(visited_p, 0, sizeof(visited_p));
    queue[rear++] = (Node){sx, sy, 0};
    visited_p[sy][sx] = 1;

    while (front < rear) {
        Node now = queue[front++];

        // 如果到达边界,就可以逃生
        if (now.x == 0 || now.x == m - 1 || now.y == 0 || now.y == n - 1) {
            ex = now.x;
            ey = now.y;
            return 1;
        }

        for (int d = 0; d < 4; d++) {
            int nx = now.x + dx[d];
            int ny = now.y + dy[d];

            if(!visited_p[ny][nx] &&
            nx >= 0 && nx < n && ny >= 0 && ny < m &&
            map[ny][nx] != '#' && now.step + 1 < monster[ny][nx]){
            visited_p[ny][nx] = 1;
            prev_dir[ny][nx] = dirChar[d];
            queue[rear++] = (Node){nx, ny, now.step + 1};
            }
        }
    }
    return  0;
}

int printPath(int sx, int sy, int ex, int ey) {  //记录并输出路径
    char path[MAXN * MAXN];
    int len = 0;
    int x = ex,y = ey;
    while (!(x == sx && y == sy)){
        char d = prev_dir[y][x]; //从哪个方向走过来的
        path[len++] = d;
        if (d == 'U')
            y += 1;
        else if (d == 'D')
            y -= 1;
        else if (d == 'L')
            x += 1;
        else if (d == 'R')
            x -= 1;

    }
    for (int i = 0; i < len / 2; ++i) {//路径反转
        swap(&path[i], &path[len - 1 - i]);
    }
    printf("YES\n");
    printf("%d\n %s\n",len ,path);
}
int main(){
    scanf("%d %d",&n, &m);
    int sx,sy,ex,ey;
    int i,j;
    for(i = 0; i < n; i++){
        for(j = 0; j < m; j++){
            scanf(" %c", &map[i][j]);
            if (map[i][j] == 'A') {
                sx = j;
                sy = i;
            }
        }
    }
    BFS_m();
    if (BFS_p(sx, sy)) {
        printPath(sx, sy, ex, ey);
    } else {
        printf("NO\n");
    }
    return 0;
}
posted @ 2025-05-12 00:27  sirro1uta  阅读(31)  评论(0)    收藏  举报