코딩하는 고릴라

[Javascript] BOJ_20055. 컨베이어 벨트 위의 로봇 본문

APS

[Javascript] BOJ_20055. 컨베이어 벨트 위의 로봇

코릴라입니다 2023. 12. 30. 10:17
반응형

🦍 문제

 

20055번: 컨베이어 벨트 위의 로봇

길이가 N인 컨베이어 벨트가 있고, 길이가 2N인 벨트가 이 컨베이어 벨트를 위아래로 감싸며 돌고 있다. 벨트는 길이 1 간격으로 2N개의 칸으로 나뉘어져 있으며, 각 칸에는 아래 그림과 같이 1부

www.acmicpc.net


🐈 문제 풀이

1. 무엇을 구해야 할까?

 - 컨베이어의 회전, 로봇의 이동, 로봇을 컨베이어 위에 올리는 작업을 한 단계로 하여 몇 단계를 거쳐야 컨베이어 벨트 중에서 내구도가 0인 칸의 개수가 K개 이상이 되는지를 구해야 한다.

2. 어떻게 구해야 할까?

 - 컨베이어 벨트의 상태를 구현한 후, 해당 상태를 조작하는 여러 함수들을 작성해 구할 수 있다.

 - Conveyor라는 클래스를 선언한 후, 내부에서 상태와 함수들을 작성하였다.

 

2.1. 컨베이어 벨트의 상태

 - belt : 크기가 2 * N인 배열. 배열의 각 칸에 [해당 칸의 내구도, 해당 칸의 로봇 존재 여부] 로 상태를 저장

 - liftPoint : 로봇을 올리는 지점

 - dropPoint : 로봇을 하차하는 지점

    - 컨베이어 벨트 회전을 배열 내 값의 물리적 이동이 아닌 논리적 이동을 통해 구현할 때 사용

 

2.2. 로봇 상차

 - 상차 지점의 내구도, 로봇 존재 여부를 고려하여 로봇 상차

 - 로봇 상차 후 내구도 체크를 통해 벨트 내구도가 0인지 아닌지 체크

 

2.3. 로봇 하차

  - 하차 지점에 로봇이 존재하면 로봇 하차

 

 

2.4. 내구도 체크

  - 입력받은 지점의 내구도가 0인 경우 breakPoints 변수 1 증가

 

2.5. 벨트 회전

 - liftPoint, dropPoint 변수 값만을 변경해 벨트의 회전을 구현

 - 벨트 회전 후 로봇 하차

 

2.6. 로봇 이동

 - dropPoint에서부터 거꾸로하여 liftPoint까지 로봇을 한 칸씩 앞으로 이동

 - 로봇의 존재 여부, 벨트의 내구도를 고려하여 조건문 작성

 - 로봇 이동 후 내구도 체크 진행

 

3. 특별히 고려해야 할 사항은?

 - 벨트의 상태를 어떤 식으로 구조화 할지, 해당 상태를 어떤 식으로 조작해 기능을 구현할 지 생각해보면 좋을 것 같다.


🐕‍🦺 소스 코드

//초기 설정
const input = require("fs")
  .readFileSync("/dev/stdin")
  .toString()
  .trim()
  .split("\n");
const [N, K] = input[0].split(" ").map(Number);

class Conveyor {
  constructor(durabilities) {
    // 벨트 설정 [내구도, 로봇 존재 여부]
    this.belt = Array(2 * N)
      .fill(0)
      .map((element, idx) => [durabilities[idx], false]);
    this.liftPoint = 0; // 로봇 상차지점
    this.dropPoint = N - 1; // 로봇 하차지점
    this.breakPoints = 0; // 고장난 칸 개수
  }

  // 벨트 회전시키기
  rotateBelt() {
    this.liftPoint--;
    this.dropPoint--;

    // 상차, 하차지점이 벨트를 벗어났을 경우 보정
    if (this.liftPoint < 0) {
      this.liftPoint += 2 * N;
    }
    if (this.dropPoint < 0) {
      this.dropPoint += 2 * N;
    }

    // 로봇 하차
    this.dropRobot();
  }

  // 로봇 상차하기
  liftRobot() {
    // 상차지점의 내구도가 0보다 크고 로봇이 없을 때
    if (this.belt[this.liftPoint][0] > 0 && !this.belt[this.liftPoint][1]) {
      this.belt[this.liftPoint][1] = true;
      this.belt[this.liftPoint][0]--;
      this.checkDurability(this.liftPoint);
    }
  }

  // 로봇 하차하기
  dropRobot() {
    if (this.belt[this.dropPoint][1]) {
      this.belt[this.dropPoint][1] = false;
    }
  }

  // 로봇 이동시키기
  moveRobot() {
    for (let i = this.dropPoint; i > this.dropPoint - N; i--) {
      let cur = i >= 0 ? i : i + 2 * N;
      let pre = cur - 1 >= 0 ? cur - 1 : cur - 1 + 2 * N;

      // 현재 보고있는 컨베이어 벨트 칸의 내구도가 0보다 크고 로봇이 없을 때, 이동시킬 로봇이 존재할 때
      if (this.belt[cur][0] > 0 && !this.belt[cur][1] && this.belt[pre][1]) {
        this.belt[cur][0]--; // 내구도 감소
        this.belt[cur][1] = true; // 로봇 이동
        this.belt[pre][1] = false; // 로봇 이동
        this.checkDurability(cur);
      }
    }

    this.dropRobot();
  }

  checkDurability(num) {
    if (this.belt[num][0] === 0) {
      this.breakPoints++;
    }
  }
}

(function solution() {
  const conveyor = new Conveyor(input[1].split(" ").map(Number));

  let i = 0;
  while (conveyor.breakPoints < K) {
    conveyor.rotateBelt();
    conveyor.moveRobot();
    conveyor.liftRobot();
    ++i;
  }
  console.log(i);
})();


🐖 Think

 - 상태 설정과 이를 조작하는데 있어 큰 어려움은 없었던 문제였다.

 

 
 
반응형