프로그래밍/알고리즘

BOJ 5980 · Corn Maze

반응형


알고리즘 분류 : BFS  


BFS를 이용하여 미로 탈출을 하는 것을 구현해야 한다. 일반적인 탈출 BFS와 같으나, 맵에서 순간 이동이 가능하다. 순간 이동하는 부분을 잘 처리하는 것이 관건이다.


  • 출발점(@)부터 출구(=)까지 도달하는 최단 거리를 구해야 한다.
  • 순간 이동(A~Z)는 쌍으로 이루어져 있으며, 이동 비용은 없다.
  • 알파벳 총개수(26) 만큼 리스트를 만들어 둔다. 입력받을 때, 대문자 알파벳인 경우 해당 좌표를 리스트에 저장한다.
  • BFS를 통해 이동하다가 순간 이동 입구에 도착하면, 리스트에 있는 좌표를 꺼내서 반대편 입구로 넘어간다. 넘어간 곳의 좌표를 큐에 집어넣는다.
  • 풀(.)이면 일반적인 이동이 가능하다. 방문 체크를 하고, 이동 좌표를 큐에 집어넣는다.
  • 위 과정을 출구에 도착할 때까지 반복한다.





C++ 소스코드


#include <cstdio>
#include <queue>
#include <vector>
using namespace std;

struct maze {
    int x, y, d;
};

int n, m;
char a[301][301];
bool check[300][300];
vector<maze> v[26];
queue<maze> q;
const int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};

void bfs() {
    while (!q.empty()) {
        int x = q.front().x, y = q.front().y, d = q.front().d; q.pop();
        if (a[x][y] == '=') {
            printf("%d\n", d);
            return;
        }
        for (int i=0; i<4; i++) {
            int nx = x+dx[i], ny = y+dy[i];
            if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
            if (check[nx][ny] || a[nx][ny] == '#') continue;
            int c = a[nx][ny]-'A';
            if (0 <= c && c <= 25) {
                if (nx == v[c][0].x && ny == v[c][0].y) {
                    nx = v[c][1].x;
                    ny = v[c][1].y;
                } else {
                    nx = v[c][0].x;
                    ny = v[c][0].y;
                }
            } else {
                check[nx][ny] = true;
            }
            q.push({nx, ny, d+1});
        }
    }
}

int main() {
    scanf("%d %d", &n, &m);
    for (int i=0; i<n; i++) {
        for (int j=0; j<m; j++) {
            char c;
            scanf(" %1c", &c);
            a[i][j] = c;
            if ('A' <= c && c <= 'Z') {
                v[c-'A'].push_back({i, j});
            } else if (c == '@') {
                q.push({i, j, 0});
                check[i][j] = true;
            }
        }
    }
    bfs();
    return 0;
}




Python 3 소스코드


from sys import stdin
from collections import deque
input = stdin.readline

n, m = map(int, input().split())
a = [list(input().strip()) for _ in range(n)]
check = [[False]*m for _ in range(n)]
v = [[] for _ in range(26)]
q = deque()

def bfs():
    while q:
        x, y, d = q.popleft()
        if a[x][y] == '=':
            print(d)
            return
        for dx, dy in (-1,0), (1,0), (0,-1), (0,1):
            nx, ny = x+dx, y+dy
            if nx < 0 or nx >= n or ny < 0 or ny >= m:
                continue
            if not check[nx][ny] and a[nx][ny] != '#':
                k = ord(a[nx][ny])-65
                if 0 <= k <= 25:
                    if len(v[k]) != 2:
                        continue
                    if (nx, ny) == v[k][0]:
                        nx, ny = v[k][1]
                    else:
                        nx, ny = v[k][0]
                else:
                    check[nx][ny] = True
                q.append((nx, ny, d+1))

for i in range(n):
    for j in range(m):
        c = a[i][j]
        if 'A' <= c <= 'Z':
            v[ord(c)-65].append((i, j))
        elif c == '@':
            q.append((i, j, 0))
            check[i][j] = True
bfs()




참고



반응형