치춘짱베리굿나이스

[백준] 5427 본문

문제

상근이는 빈 공간과 벽으로 이루어진 건물에 갇혀있다. 건물의 일부에는 불이 났고, 상근이는 출구를 향해 뛰고 있다.

매 초마다, 불은 동서남북 방향으로 인접한 빈 공간으로 퍼져나간다. 벽에는 불이 붙지 않는다. 상근이는 동서남북 인접한 칸으로 이동할 수 있으며, 1초가 걸린다. 상근이는 벽을 통과할 수 없고, 불이 옮겨진 칸 또는 이제 불이 붙으려는 칸으로 이동할 수 없다. 상근이가 있는 칸에 불이 옮겨옴과 동시에 다른 칸으로 이동할 수 있다.

빌딩의 지도가 주어졌을 때, 얼마나 빨리 빌딩을 탈출할 수 있는지 구하는 프로그램을 작성하시오.

입력

첫째 줄에 테스트 케이스의 개수가 주어진다. 테스트 케이스는 최대 100개이다.

각 테스트 케이스의 첫째 줄에는 빌딩 지도의 너비와 높이 w와 h가 주어진다. (1 ≤ w,h ≤ 1000)

다음 h개 줄에는 w개의 문자, 빌딩의 지도가 주어진다.

  • '.': 빈 공간
  • '#': 벽
  • '@': 상근이의 시작 위치
  • '*': 불

각 지도에 @의 개수는 하나이다.

출력

각 테스트 케이스마다 빌딩을 탈출하는데 가장 빠른 시간을 출력한다. 빌딩을 탈출할 수 없는 경우에는 "IMPOSSIBLE"을 출력한다.

풀이

class Node {
  constructor(data, prev = null, next = null) {
    this.data = data;
    this.prev = prev;
    this.next = next;
  }
}

class Queue {
  constructor() {
    this.head = new Node(-1);
    this.tail = new Node(-1);
    this.head.next = this.tail;
    this.tail.prev = this.head;
    this.size = 0;
  }
  enQueue(data) {
    let node = new Node(data);
    node.next = this.tail;
    node.prev = this.tail.prev;
    this.tail.prev.next = node;
    this.tail.prev = node;
    this.size++;
  }
  deQueue() {
    if (this.ifEmpty()) return -1;
    let tmp = this.head.next;
    tmp.next.prev = this.head;
    this.head.next = tmp.next;
    this.size--;
    return tmp.data;
  }
  ifEmpty() {
    return this.size ? false : true;
  }
}

const sangeunMove = (fireArr, sangeunArr, row, col, sangeunPos) => {
  let queue = new Queue();
  const dir = [
    [1, 0, -1, 0],
    [0, 1, 0, -1],
  ];
  queue.enQueue(sangeunPos);
  sangeunArr[sangeunPos[0]][sangeunPos[1]] = 1;
  while (!queue.ifEmpty()) {
    let cur = queue.deQueue();
    for (let i = 0; i < 4; i++) {
      let coord = [cur[0] + dir[0][i], cur[1] + dir[1][i]];
      if (coord[0] < 0 || coord[0] >= col || coord[1] < 0 || coord[1] >= row)
        return sangeunArr[cur[0]][cur[1]];
      if (!(sangeunArr[coord[0]][coord[1]] === ".")) continue;
      if (sangeunArr[cur[0]][cur[1]] + 1 > fireArr[coord[0]][coord[1]])
        continue;
      sangeunArr[coord[0]][coord[1]] = sangeunArr[cur[0]][cur[1]] + 1;
      queue.enQueue([coord[0], coord[1]]);
    }
  }
  return "IMPOSSIBLE";
};

const fireMove = (fireArr, row, col) => {
  let queue = new Queue();
  let sangeun;
  const dir = [
    [1, 0, -1, 0],
    [0, 1, 0, -1],
  ];
  for (let i = 0; i < col; i++) {
    for (let j = 0; j < row; j++) {
      if (fireArr[i][j] === "*") {
        queue.enQueue([i, j]);
        fireArr[i][j] = 0;
      } else if (fireArr[i][j] === "@") sangeun = [i, j];
    }
  }

  while (!queue.ifEmpty()) {
    let size = queue.size;
    for (let i = 0; i < size; i++) {
      let cur = queue.deQueue();
      for (let j = 0; j < 4; j++) {
        let coord = [cur[0] + dir[0][j], cur[1] + dir[1][j]];
        if (coord[0] < 0 || coord[0] >= col || coord[1] < 0 || coord[1] >= row)
          continue;
        if (
          !(
            fireArr[coord[0]][coord[1]] === "." ||
            fireArr[coord[0]][coord[1]] === "@"
          )
        )
          continue;
        fireArr[coord[0]][coord[1]] = fireArr[cur[0]][cur[1]] + 1;
        queue.enQueue([coord[0], coord[1]]);
      }
    }
  }
  return sangeun;
};

const fire = () => {
  let input = require("fs")
    .readFileSync("/dev/stdin")
    .toString()
    .trim()
    .split("\\n");
  let len = parseInt(input[0]);
  let i = 1;
  let ans = [];
  while (len--) {
    let row = parseInt(input[i].split(" ")[0]);
    let col = parseInt(input[i].split(" ")[1]);
    i++;
    let fireArr = input.slice(i, i + col).map((n) => n.split(""));
    let sangeunArr = input.slice(i, i + col).map((n) => n.split(""));
    let sangeun = fireMove(fireArr, row, col);
    ans.push(sangeunMove(fireArr, sangeunArr, row, col, sangeun));
    i += col;
  }
  console.log(ans.join("\\n"));
};

fire();

반성회

불! 의 응용편

https://blog.chichoon.com/371 에서 테스트케이스를 여러 개 받느라 for문이 하나 더 추가된 형태이다

'Javascript + Typescript > 자바스크립트로 알고리즘풀기' 카테고리의 다른 글

[백준] 2558  (0) 2022.03.10
[백준] 1292  (0) 2022.03.10
[백준] 7562  (0) 2022.03.10
[백준] 7569  (0) 2022.03.10
[백준] 1094  (0) 2022.03.10
Comments