본문 바로가기
Development/자료구조 & 알고리즘

[알고리즘] 프로그래머스 - 미로탈출 (JS)

by heondeam 2023. 9. 18.

 

✅ 문제

1 x 1 크기의 칸들로 이루어진 직사각형 격자 형태의 미로에서 탈출하려고 합니다. 각 칸은 통로 또는 벽으로 구성되어 있으며, 벽으로 된 칸은 지나갈 수 없고 통로로 된 칸으로만 이동할 수 있습니다. 통로들 중 한 칸에는 미로를 빠져나가는 문이 있는데, 이 문은 레버를 당겨서만 열 수 있습니다. 레버 또한 통로들 중 한 칸에 있습니다. 따라서, 출발 지점에서 먼저 레버가 있는 칸으로 이동하여 레버를 당긴 후 미로를 빠져나가는 문이 있는 칸으로 이동하면 됩니다. 이때 아직 레버를 당기지 않았더라도 출구가 있는 칸을 지나갈 수 있습니다. 미로에서 한 칸을 이동하는데 1초가 걸린다고 할 때, 최대한 빠르게 미로를 빠져나가는데 걸리는 시간을 구하려 합니다.

미로를 나타낸 문자열 배열 maps가 매개변수로 주어질 때, 미로를 탈출하는데 필요한 최소 시간을 return 하는 solution 함수를 완성해주세요. 만약, 탈출할 수 없다면 -1을 return 해주세요.

 

✅ 풀이

BFS를 사용해서 풀이했다. 처음 생각했던 코드는 레버를 찾는 것과 출구를 찾는 것을 한번의 BFS 함수에서 동시에 진행하는 방식이었고 시간초과가 발생했다.

 

추가적으로 생각해낸 풀이는 레버를 찾는 BFS 함수와 출구를 찾는 BFS 함수를 나누어 진행하는 것이었다. 그리고 해당 코드로 모든 테스트 케이스를 통과할 수 있었다.

 

결국 레버를 찾는 가장 짧은 시간 + 출구를 찾는 가장 짧은 시간을 구하는 문제라고 생각하면 될 것 같다. 풀이는 아래와 같다.

 

function solution(maps) {
  let answer = [];
  let sum = 0;
  const maxX = maps.length;
  const maxY = maps[0].length;
  const newMaps = [];
  const [dX, dY] = [[-1, 0, 1, 0], [0, 1, 0, -1]];
  
  let startPos;
  let leverPos;
  
  for (let i = 0; i < maps.length; i ++) {
    newMaps.push([]);
    
    for (let j = 0; j < maps[i].length; j ++) {
      newMaps[i].push(maps[i][j]);
      
      if (maps[i][j] === "S") {
        startPos = [i, j];
      }
      
      if (maps[i][j] === "L") {
        leverPos = [i, j];
      }
    }
  }
  
  function BFS(x, y, o) {

    const queue = [[x, y, 0]];
    const visited = [];
    
    for (let i = 0; i < maxX; i ++) {
      visited.push([]);
      for (let j = 0; j < maxY; j ++) {
        visited[i].push(0);
      }
    }
    
    visited[x][y] = 1;
    
    while(queue.length) {
      const [nX, nY, nT] = queue.shift();
      
      for (let i = 0; i < 4; i ++) {
        const [sX, sY] = [nX + dX[i], nY + dY[i]];
        
        if ((sX >= 0 && sX < maxX) && (sY >= 0 && sY < maxY)) {
          if (maps[sX][sY] !== "X" && visited[sX][sY] === 0) {            
            // 갈 수 있음.
            if (maps[sX][sY] === o) {
              answer.push(nT + 1);
              sum += nT + 1;
              return;
            }else {
              queue.push([sX, sY, nT + 1]);
              visited[sX][sY] = 1
            }
          }            
        }
      }
    }
  } 
  
  BFS(startPos[0],startPos[1], "L");
  BFS(leverPos[0],leverPos[1], "E");
  
  
  return answer.length > 1 ? sum : -1;
}

댓글