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};
}
}
}
}
点击查看代码
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);
}
完整代码如下
点击查看代码
#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;
}

浙公网安备 33010602011771号