Algorithm

[백준] 14503번: 로봇 청소기 - Node.js (자바스크립트)

sqsung 2023. 6. 21. 11:57

1. 문제 ㅡ 14503번: 로봇 청소기 (난이도: Gold V)

 

14503번: 로봇 청소기

첫째 줄에 방의 크기 $N$과 $M$이 입력된다. $(3 \le N, M \le 50)$  둘째 줄에 처음에 로봇 청소기가 있는 칸의 좌표 $(r, c)$와 처음에 로봇 청소기가 바라보는 방향 $d$가 입력된다. $d$가 $0$인 경우 북쪽

www.acmicpc.net

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

class Queue {
  constructor(initValue) {
    this.q = initValue ? [initValue] : [];
    this.head = 0;
    this.tail = initValue ? 1 : 0;
  }

  push(item) {
    this.q[this.tail] = item;
    this.tail++;
  }

  shift() {
    this.head++;
    return this.q[this.head - 1];
  }

  isEmpty() {
    return this.head === this.tail;
  }
}

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

const getRobotMoves = input => {
  const [Y, X] = input.shift().split(' ').map(val => +val);
  const [sY, sX, direction] = input.shift().split(' ').map(val => +val);
  const room = input.map(row => row.split(' ').map(val => +val));
  
  /**
  * @cleaned: 이미 청소 완료한 칸의 좌표 저장
  * @dirs: 0 - 상, 1 - 우, 2 - 남, 3 - 좌
  */ 
  const cleaned = Array.from({ length: Y }).map(() => Array.from({ length: X }, () => false));
  const dirs = { 0: [0, -1], 1: [1, 0], 2: [0, 1], 3: [-1, 0] };
  
  const q = new Queue([sX, sY, direction]); 
  let moves = 0;

  while (!q.isEmpty()) {
    let [x, y, direction] = q.shift(); 

    if (room[y][x] === 0 && !cleaned[y][x]) {
      moves += 1;
      cleaned[y][x] = true; 
    }

    for (let i = 0; i < 4; i++) {
      direction = direction - 1 < 0 ? (direction - 1) + 4 : direction - 1;
      const [newX, newY] = [x + dirs[direction][0], y + dirs[direction][1]];
      
      if (room[newY][newX] === 0 && !cleaned[newY][newX]) {
        q.push([newX, newY, direction]);
        break; 
      } 

      if (i === 3) {
        const back = direction - 2 < 0 ? (direction - 2) + 4 : direction - 2;
        const [backX, backY] = [x + dirs[back][0], y + dirs[back][1]];
    
        if (room[backY][backX] === 0) q.push([backX, backY, direction]);
      }
    }
  }

  return moves; 
};

console.log(getRobotMoves(input));

 

2-1. 풀이 설명

로봇 청소기의 동작 방식만 이해하면 어렵지 않은 BFS 문제다. ▼

로봇 청소기의 출발 지점(좌표)과 방향을 queue에 넣어두고 BFS를 하면 된다.

 

  • 현재 로봇 청소기가 위치한 칸이 청소되지 않은 상태면 현재 칸을 청소한다 (= moves를 1 증가 시킨다)
  • 현재 로봇 청소기의 방향(동서남북)을 기준으로 반시계 방향으로 회전한다. 0, 1, 2, 3을 상, 좌, 하, 우로 지정해두었고, 로봇 청소기의 방향에서 1을 빼서 (음수인 경우 1을 뺀 후 4를 더해줌) 회전된 방향을 계산했다.   
  • 회전 후 정면에 청소되지 않은 칸이 있는 경우 청소기를 해당 칸으로 이동, 즉 queue에 새로운 좌표와 현재 방향을 넣어줬다
  • 인접 칸을 모두 확인했는데 청소할 수 있는 칸이 없는 경우, 청소기가 후진할 수 있는 칸이 있는지 확인한 후 후진시켰다. 후진 방향을 계산하기 위해 청소기의 현재 방향에서 2를 뺐다 (음수인 경우 2를 뺀 후 4를 더해줌). 청소기가 후진할 때는 현재 방향을 유지하므로, queue에 새로운 좌표와 방향을 넣어줄 때 방향은 원래 방향을 다시 넣어줘야 한다.