alorithm/programmers

[프로그래머스] 미로 탈출

Hannana. 2024. 8. 13. 02:03
728x90
반응형

문제 파악

-시작점에서 도착지점까지 한 칸씩 이동하며 카운트하기

-레버 만나야 도착지점으로 갈 수 있음

  • 5 ≤ maps의 길이 ≤ 100
    • 5 ≤ maps[i]의 길이 ≤ 100
    • maps[i]는 다음 5개의 문자들로만 이루어져 있습니다.
      • S : 시작 지점
      • E : 출구
      • L : 레버
      • O : 통로
      • X : 벽
    • 시작 지점과 출구, 레버는 항상 다른 곳에 존재하며 한 개씩만 존재합니다.
    • 출구는 레버가 당겨지지 않아도 지나갈 수 있으며, 모든 통로, 출구, 레버, 시작점은 여러 번 지나갈 수 있습니다.

 

 

접근 방법

-시작점 S가 어디에 있는지 먼저 찾아서 거기서부터 각 방향으로 갈 수 있는지 유효성 검사(isValid)

-갈 수 있는 방향 따라 가면서 큐에 가능한 경로 좌표 담기

-bfs를 활용해 도착지점까지 최소거리 구하기(큐에 담을 때는 x,y좌표와 한칸씩 이동하면서 카운트 세기)

-좌표 담기 전 유효성 검사와 방문 여부 검사하고, 통과하면 큐에 담기

-목적지 가는 도중 레버를 들려야 하므로, 레버까지의 bfs를 구해 카운트 변수에 따로 빼주고,

-레버에서 목적지까지 bfs를 구해 위의 레버까지의 최소거리와 더한다. ⇒ 결과값 리턴

-만일 도착 지점 혹은 출발 지점에 X가 가로막혀있거나,

레버를 찾을 수 없어 도착지점에 도달할 수 없다면 -1리턴

 

코드 구현

import java.util.*;
class Solution {
    public int solution(String[] maps) {
        int n=maps.length;
        int m=maps[0].length();
        Queue<int[]> que=new ArrayDeque<>();
        boolean[][] visited = new boolean[n][m];
        
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                char c=maps[i].charAt(j);
                if(c=='S'){//시작점
                    if(isValid(i,j,maps) && !visited[i][j]){
                        que.offer(new int[]{i,j,0});
                        visited[i][j]=true;
                    }
                }
            }
        }
        int[] dx = {-1, 1, 0, 0};
        int[] dy = {0, 0, -1, 1};
        int lx=0;int ly=0;int findl=0;
        while(!que.isEmpty()){
            int[] node = que.poll();
            int cx = node[0];
            int cy = node[1];
            int cnt = node[2];
            if (maps[cx].charAt(cy) == 'L') {
                lx=cx;
                ly=cy;
                findl=cnt;
                break;
            }
            for (int i = 0; i < 4; i++) {
                int x = cx + dx[i];
                int y = cy + dy[i];
                if(isValid(x,y,maps) && !visited[x][y]){
                    que.offer(new int[]{x,y,cnt+1});
                    visited[x][y]=true;
                }
            }
        }
        if(findl==0) return -1;
        que.clear();
        visited=new boolean[n][m];
        que.offer(new int[]{lx, ly, 0});
        visited[lx][ly] = true;//레버부터 시작

        while(!que.isEmpty()){
            int[] node = que.poll();
            int cx = node[0];
            int cy = node[1];
            int cnt = node[2];
            
            for (int i = 0; i < 4; i++) {
                int x = cx + dx[i];
                int y = cy + dy[i];
                if(isValid(x,y,maps) && !visited[x][y]){
                    if (maps[x].charAt(y) == 'E') {
                        return cnt +=findl+1;
                    }
                    que.offer(new int[]{x,y,cnt+1});
                    visited[x][y]=true;
                }
            }
        }
        return -1;
    }
    public boolean isValid(int x,int y,String[] maps){
        if(x<0 || x>=maps.length || y<0 || y>=maps[0].length() || maps[x].charAt(y) == 'X'){
            return false;
        }
        return true;
    }
}

배우게 된 점

-출발-도착으로의 최소 거리만 구해봐서 레버가 무엇을 의미하는지 몰랐는데,

제출하니 오류가 나서 문제를 다시 보니 레버가 결과까지 가기에 중요한 역할을 했다.

-즉, 레버를 꼭 방문해야만 하는 것. 레버를 방문하고 레버를 기점으로 목적지까지 가야하니

각 경로를 두개로 나누어 최소거리를 구한다. 그리고 두개를 더해야 정답 완성

-isValid함수 작성 시, 범위 설정에 주의하자.

 

 

 

반응형

'alorithm > programmers' 카테고리의 다른 글

[LeetCode] Shortest Path in Binary Matrix  (0) 2024.08.13
[프로그래머스] 게임 맵 최단거리  (0) 2024.08.13
[LeetCode] Keys and Rooms  (0) 2024.08.13
[LeetCode] Is Graph Bipartite?  (0) 2024.08.13
[LeetCode] Coin Change  (0) 2024.08.13