본문 바로가기
Algorithm

프로그래머스 <미로 탈출 명령어>

by seungh2 2023. 8. 21.

프로그래머스 <미로 탈출 명령어>

https://school.programmers.co.kr/learn/courses/30/lessons/150365

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr


미로 탈출 명령어

N * M 격자 미로가 있을 때, (x, y)에서 출발해서 (r, c)까지 이동하려고 한다. 이때 아래의 규칙을 지키며 이동한다.

격자 바깥으로 나갈 수 없다.

이동하는 거리는 총 K여야 한다. 같은 격자를 2번 이상 방문해도 된다.

미로에서 탈출한 경로를 문자열로 나타냈을 때, 문자열이 사전 순으로 가장 빠른 경로여야 한다.

 

이동경로를 문자열로 바꾸는 것은 l -> 왼쪽, r -> 오른쪽, u -> 위쪽, d -> 아래쪽이다.


문제해결

BFS를 이용해서 문제를 해결했다.

 

같은 격자를 2번 이상 방문해도 되기 때문에 방문체크 배열을 3차원으로 사용하였다. 또한 이동경로를 알아야 하기 때문에 이전 이동 정보를 담은 prev 배열을 3차원으로 사용하였다.

visit[i][j][k] : (i, j) 좌표까지 k거리로 왔었으면 true

prev[i][j][k] : (i, j) 좌표까지 k거리로 왔을 때 이전 좌표와 어느 방향으로 왔는지가 저장되어 있다.

 

사전순으로 경로가 앞서야 하기 때문에 인접 노드를 계산하는 di, dj 배열을 d, l, r, u 순으로 만들었다.

 

자세한 로직은 다음과 같다.

  • 큐에 시작 노드를 넣는다.
  • 큐의 크기만큼 for문을 돌린다. -> 같은 거리의 노드를 처리한다.
    • 큐에서 노드를 꺼내고, 해당 노드의 인접 노드를 dist+1만큼의 거리로 오지 않았다면 방문한다. 
    • 방문 표시를 하고, 이전 노드를 기록한다.
    • 만약 인접노드가 도착 노드이고 dist+1의 값이 K라면 정답을 찾은 것이므로 정답 문자열을 만들러 간다. -> answer()
  • dist가 K라면 더이상 진행하지 않는다.

코드

import java.util.*;
class Solution {
    static int N, M, K;
    static Tuple Start, End;
    static int[] di = {1, 0, 0, -1};
    static int[] dj = {0, -1, 1, 0};
    static class Tuple{
        int x, y;
        public Tuple(int x, int y){
            this.x = x;
            this.y = y;
        }
        int d;
        public Tuple(int x, int y, int d){
            this.x = x;
            this.y = y;
            this.d = d;
        }
        
    }
    public String solution(int n, int m, int x, int y, int r, int c, int k) {
        String answer = "";
        N = n; 
        M = m;
        K = k;
        Start = new Tuple(x-1, y-1);
        End = new Tuple(r-1, c-1);
        
        return BFS();
    }
    static String BFS(){
        boolean[][][] visit = new boolean[N][M][K+1];
        Tuple[][][] prev = new Tuple[N][M][K+1];
        Queue<Tuple> Q = new ArrayDeque<>();
        visit[Start.x][Start.y][0] = true;
        Q.add(new Tuple(Start.x, Start.y));
        
        int dist = 0;
        while(!Q.isEmpty()){
            int size = Q.size();
            for(int p = 0; p < size; p++){
                Tuple tp = Q.poll();
                for(int k = 0; k < 4; k++){
                    int ni = tp.x + di[k];
                    int nj = tp.y + dj[k];
                    if (ni < 0 || nj < 0 || ni >= N || nj >= M || visit[ni][nj][dist+1]) continue;
                    visit[ni][nj][dist+1] = true;
                    prev[ni][nj][dist+1] = new Tuple(tp.x, tp.y, k);
                    if(dist+1 == K && ni == End.x && nj == End.y){
                        return answer(prev);
                    }
                    Q.add(new Tuple(ni, nj));
                }
            }
            dist++;
            if(dist == K) break;
        }
        return "impossible";
    }
    static char[] dir = {'d', 'l', 'r', 'u'};
    static String answer(Tuple[][][] prev){
        StringBuffer sb = new StringBuffer();
        int dist = K;
        Tuple tp = prev[End.x][End.y][dist--];
        while(tp != null){
            sb.append(dir[tp.d]);
            tp = prev[tp.x][tp.y][dist--];
        }
        return sb.reverse().toString();
    }
}

결과


 

728x90

'Algorithm' 카테고리의 다른 글

백준 2879번 <코딩은 예쁘게>  (0) 2023.08.23
백준 1256번 <사전>  (0) 2023.08.22
백준 7490번 <0 만들기>  (0) 2023.08.21
백준 18427번 <함께 블록 쌓기>  (0) 2023.08.19
백준 1976번 <여행 가자>  (0) 2023.08.18

댓글