YataNox
[Java] Lv.2 미로 탈출 본문
문제
문제 설명
1 x 1 크기의 칸들로 이루어진 직사각형 격자 형태의 미로에서 탈출하려고 합니다.
각 칸은 통로 또는 벽으로 구성되어 있으며,
벽으로 된 칸은 지나갈 수 없고 통로로 된 칸으로만 이동할 수 있습니다.
통로들 중 한 칸에는 미로를 빠져나가는 문이 있는데, 이 문은 레버를 당겨서만 열 수 있습니다.
레버 또한 통로들 중 한 칸에 있습니다.
따라서, 출발 지점에서 먼저 레버가 있는 칸으로 이동하여 레버를 당긴 후
미로를 빠져나가는 문이 있는 칸으로 이동하면 됩니다.
이때 아직 레버를 당기지 않았더라도 출구가 있는 칸을 지나갈 수 있습니다.
미로에서 한 칸을 이동하는데 1초가 걸린다고 할 때,
최대한 빠르게 미로를 빠져나가는데 걸리는 시간을 구하려 합니다.
미로를 나타낸 문자열 배열 maps가 매개변수로 주어질 때,
미로를 탈출하는데 필요한 최소 시간을 return 하는 solution 함수를 완성해주세요.
만약, 탈출할 수 없다면 -1을 return 해주세요.
제한사항
5 ≤ maps의 길이 ≤ 100
5 ≤ maps[i]의 길이 ≤ 100
maps[i]는 다음 5개의 문자들로만 이루어져 있습니다.
S : 시작 지점
E : 출구
L : 레버
O : 통로
X : 벽
시작 지점과 출구, 레버는 항상 다른 곳에 존재하며 한 개씩만 존재합니다.
출구는 레버가 당겨지지 않아도 지나갈 수 있으며, 모든 통로, 출구, 레버, 시작점은 여러 번 지나갈 수 있습니다.
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
문제 풀이
일반적인 BFS 문제인데, 2번 돌려야한다.
출발점에서 레버의 위치를 찾는 BFS 한 번, 레버의 위치에서 도착점의 위치를 찾는 BFS 한 번
자바 코드
import java.util.*;
class Solution {
public boolean[][] visited;
public int[][] minTime;
// 상 하 좌 우
public int[] dx = {-1, 1, 0, 0}, dy = {0, 0, -1, 1};
public boolean isFindLever = false, isFindExit = false;
public int n = 0, m = 0;
public int sx, sy, lx, ly, ex, ey;
public class Point {
int x;
int y;
Point(int x, int y) {
this.x = x;
this.y = y;
}
}
public int solution(String[] maps) {
// maps 크기
n = maps.length;
m = maps[0].length();
// 방문처리 배열과 최소 시간 기록 배열
visited = new boolean[n][m];
minTime = new int[n][m];
// 시작점, 레버, 도착점 위치 기록
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++) {
char c = maps[i].charAt(j);
if(c == 'E') {
ex = i;
ey = j;
}
else if(c == 'S') {
sx = i;
sy = j;
}
else if(c == 'L') {
lx = i;
ly = j;
}
}
}
// 시작점 방문 처리 및 시작점부터 레버까지의 최소 시간 찾기
visited[sx][sy] = true;
bfs(sx, sy, "L", maps);
// 레버를 찾았을 경우
if(isFindLever) {
// 레버부터 도착점까지의 최소기간 찾기 시작
visited = new boolean[n][m];
visited[lx][ly] = true;
bfs(lx, ly, "E", maps);
}
// 레버와 도착점을 모두 찾았을 경우
if(isFindLever && isFindExit) {
// 도착점까지의 최소 시간 반환
return minTime[ex][ey];
}else {// 하나라도 못 찾았을 경우 -1 반환
return -1;
}
}
private void bfs(int x, int y, String findPos, String[] maps) {
Queue<Point> q = new LinkedList<>();
q.add(new Point(x, y));
// 큐 빌때까지 반복
while(!q.isEmpty()) {
// 현재 위치
Point cp = q.poll();
// 레버를 찾았을 경우
if(findPos.equals("L") && visited[lx][ly]) {
isFindLever = true;
return;
}
// 도착점을 찾았을 경우
if(findPos.equals("E") && visited[ex][ey]) {
isFindExit = true;
return;
}
for(int i = 0; i < 4; i++) {
int nx = cp.x + dx[i];
int ny = cp.y + dy[i];
// 맵의 범위를 벗어났을 경우 생략
if(nx < 0 || ny < 0 || nx >= n || ny >= m)
continue;
// 다음 칸이 장애물이 아니고 방문한 적이 없으면 해당 칸을 방문처리하고 큐에 저장
if(!(maps[nx].charAt(ny) == 'X') && !visited[nx][ny]) {
minTime[nx][ny] = minTime[cp.x][cp.y] + 1;
visited[nx][ny] = true;
q.add(new Point(nx,ny));
}
}
}
}
}
'코딩 테스트 > PROGRAMMERS' 카테고리의 다른 글
[Java] Lv.2 택배 배달과 수거하기 (0) | 2024.06.11 |
---|---|
[Java] Lv2 시소 짝꿍 (2) | 2024.06.11 |
[Java] Lv.2 혼자서 하는 틱택토 (0) | 2024.06.04 |
[Java] Lv.2 당구 연습 (0) | 2024.06.04 |
[Java] Lv.2 리코쳇 로봇 (1) | 2024.06.04 |