Sqsung DevLog

[백준] 6593번: 상범 빌딩 - Node.js (자바스크립트) 본문

Algorithm

[백준] 6593번: 상범 빌딩 - Node.js (자바스크립트)

sqsung 2023. 5. 25. 12:11

1. 문제 ㅡ 6593번: 상범 빌딩 (난이도: Gold V)

6593번: 상범 빌딩

당신은 상범 빌딩에 갇히고 말았다. 여기서 탈출하는 가장 빠른 길은 무엇일까? 상범 빌딩은 각 변의 길이가 1인 정육면체(단위 정육면체)로 이루어져있다. 각 정육면체는 금으로 이루어져 있어

www.acmicpc.net

2. 풀이 ㅡ Node.js (자바스크립트)

const input = require('fs').readFileSync('/dev/stdin').toString().trim().split('\n').map(row => row.trim());

const testCases = (() => {
  const testCases = [];

  while (input.length) {
    const [Z, Y, X] = input.shift().split(' ').map(val => +val);
    const building = [];
    
    let splitCount = 0;
    let start = { x: null, y: null, z: null };

    while (splitCount !== Z && input.length) {
      if (input[0].length === 0) {
        splitCount += 1;
        if (splitCount !== Z) building.push([]);
        input.shift();
        
        continue;
      }

      if (!building.length) building.push([]);

      const row = [...input.shift()];

      if (row.includes('S')) start = { x: row.indexOf('S'), y: building[splitCount].length, z: splitCount };
      building.at(-1).push(row);
    }

    if (Z === 0 || Y === 0 || X === 0) input.shift();
    testCases.push({ building, start, X, Y, Z });
  }

  return testCases;
})();

const dirs = [
  [1, 0, 0],
  [-1, 0, 0],
  [0, 1, 0],
  [0, -1, 0],
  [0, 0, -1],
  [0, 0, 1],
];

testCases.forEach(tc => {
  const { building, start: { x, y, z }, X, Y, Z } = tc;
  const checked = Array.from({ length: Z }).map(() =>
    Array.from({ length: Y }).map(() => Array.from({ length: X }, () => false))
  );

  if (!building.length) return;

  const queue = [[x, y, z, 0]];

  while (queue.length) {
    const [x, y, z, time] = queue.shift();

    if (building[z][y][x] === 'E') {
      console.log(`Escaped in ${time} minute(s).`);

      return;
    }

    dirs.forEach(dir => {
      const xPos = x + dir[0];
      const yPos = y + dir[1];
      const zPos = z + dir[2];

      if (xPos < 0 || yPos < 0 || zPos < 0 || xPos >= X || yPos >= Y || zPos >= Z) return;

      if (checked[zPos][yPos][xPos] || building[zPos][yPos][xPos] === '#') return;

      checked[zPos][yPos][xPos] = true;
      queue.push([xPos, yPos, zPos, time + 1]);
    });
  }

  console.log('Trapped!');
});

 

2-1. 풀이 설명

여태껏 풀어본 백준 문제 중 입력 값이 가장 불친절했던 문제다. 그래서 우선 테이스트 케이스 별로 정리해서 사용하기 편하게 해두었다. BFS 로직과 꼬여 보이지 않았으면 좋겠어서 테스트 케이스 가공 관련 로직은 즉시 실행 함수로 감싸두었다.
 
이번 문제에서는 좌우상하 칸과 함께 위, 아래로 위치한 칸도 확인해야 했다. S(시작점)을 queue에 넣어서 초기화해주고, 모든 모든 인접칸을 BFS 탐색하며 '#'이 아닌 경우, 즉 막혀있지 않은 경우 시간을 하나씩 증가시켜주어 queue에 다시 넣어줬다. 
 
queue에 들어있는 값 중 'E'의 좌표를 가지고 있는 배열이 있으면 'Escaped in ${time} minute(s).'를 출력하고 return 처리해줬다. 반대로 while문이 끝나는 동안 'E'를 못 찾은 경우에는 'Trapped!'를 출력했다. 
 

2-2. 회고

  • 분명 BFS 문제인데, BFS 관련 로직을 구현하는 건 어렵지 않은데 손가는 부분들이 많아 번거롭게 느껴졌던 문제였다. (입력값 가공부터가...)