KimMinJun
Coding Note
KimMinJun
전체 방문자
오늘
어제
  • 분류 전체보기 (486)
    • ALGORITHM (11)
      • 정렬 (6)
      • 최단경로 (1)
      • 자료구조 (1)
      • 슬라이딩 윈도우 (1)
      • etc (2)
    • Git (5)
    • Web (24)
      • Vanilla JS (13)
      • TS (2)
      • React (7)
      • ETC (1)
    • React 공식문서 (번역, 공부) (11)
      • Quick Start (2)
      • Installation (0)
      • Describing the UI (9)
      • Adding Interactivity (0)
      • Managing State (0)
      • Escape Hatches (0)
    • Next.js 공식문서 (번역, 공부) (3)
      • Getting Started (2)
      • Building Your Application (1)
    • PS (431)
      • 백준 (187)
      • Programmers (104)
      • CodeUp (21)
      • STL (3)
      • 제코베 JS 100제 (50)
      • SWEA (0)
      • LeetCode (65)
    • IT (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록
  • 관리

공지사항

인기 글

태그

  • Level 1
  • js
  • tree
  • 그래프
  • 제코베 JS 100제
  • 백준
  • 정렬
  • 수학
  • 문자열
  • Level1
  • recursion
  • C
  • 다이나믹 프로그래밍
  • LeetCode
  • Level 2
  • Level 0
  • string
  • codeup
  • programmers
  • C++

최근 댓글

최근 글

hELLO · Designed By 정상우.
KimMinJun

Coding Note

PS/백준

백준 / 그래프 / 7569번 / 토마토 / JS

2023. 4. 28. 17:47

< 문제 바로가기 >

 

7569번: 토마토

첫 줄에는 상자의 크기를 나타내는 두 정수 M,N과 쌓아올려지는 상자의 수를 나타내는 H가 주어진다. M은 상자의 가로 칸의 수, N은 상자의 세로 칸의 수를 나타낸다. 단, 2 ≤ M ≤ 100, 2 ≤ N ≤ 100,

www.acmicpc.net

 

큐를 직접 구현하지 않고 BFS를 했을 때 shift() 메소드를 사용하면 시간초과가 나서 어쩔 수 없이 구현해야 했다. 흔히 하던 전형적인 BFS 방식에서 차원수가 하나 더 늘어난 것 빼고는 크게 다를것은 없는 문제였다.

 

/* 토마토 */
const fs = require('fs');
const filePath = process.platform === 'linux' ? '/dev/stdin' : '../input.txt';
// const filePath = process.platform === 'linux' ? '/dev/stdin' : 'BOJ/input.txt';
const input = fs.readFileSync(filePath).toString().trim().split('\n');

// M = 가로(열), N = 세로(행), H = 높이
const [M, N, H] = input.shift().split(' ').map(Number);
// 1 = 익은 토마토, 0 = 익지 않은 토마토, -1 = 토마토 없음
const TOMATO_CONTAINER = input.map((row) => {
  return row.split(' ').map(Number);
});

class Node {
  constructor(value) {
    this.value = value;
    this.next = null;
  }
}

class Queue {
  constructor() {
    this.front = null;
    this.back = null;
    this.size = 0;
  }

  // queue에 맨 끝에 값 넣기
  enqueue(value) {
    const node = new Node(value);
    if (this.size === 0) {
      this.front = node;
      this.back = node;
    } else {
      this.back.next = node;
      this.back = node;
    }
    this.size++;
  }

  // queue의 맨 앞에서 빼서 반환하기
  dequeue() {
    if (this.size === 0) {
      return;
    }
    const value = this.front.value;
    this.front = this.front.next;
    this.size--;
    if (this.size === 0) this.back = null;
    return value;
  }

  // 큐가 비어있는지 판단
  isEmpty() {
    return this.size === 0;
  }
}

// 다 익으면 0, 모두 익지 못하면 -1 출력
function solution(M, N, H, TOMATO_CONTAINER) {
  let farm = [];

  const isValidIndex = (height, row, col) => {
    // height
    if (height < 0 || height >= H) {
      return false;
    }
    // row
    if (row < 0 || row >= N) {
      return false;
    }
    // col
    if (col < 0 || col >= M) {
      return false;
    }

    return true;
  };

  // 3차원 배열로 변환
  for (let k = 0; k < H * N; k += N) {
    let layer = [];
    for (let i = k; i < k + N; i += 1) {
      layer.push(TOMATO_CONTAINER[i]);
    }
    farm.push(layer);
  }

  // 3차원 배열에서의 [dz, dx, dy]
  const DIR_OBJ = {
    up: [-1, 0, 0],
    down: [1, 0, 0],
    left: [0, 0, -1],
    right: [0, 0, 1],
    front: [0, -1, 0],
    back: [0, 1, 0],
  };

  let queue = new Queue();
  let visited = Array.from({ length: H }, () =>
    Array.from({ length: N }, () => Array.from({ length: M }, () => false))
  );

  // 총 토마토의 개수
  let leftTomato = 0;
  for (let k = 0; k < H; k += 1) {
    for (let i = 0; i < N; i += 1) {
      for (let j = 0; j < M; j += 1) {
        // 익은 토마토라면
        if (farm[k][i][j] === 1) {
          // 방문처리
          visited[k][i][j] = true;
          queue.enqueue([k, i, j]);
        }
        // 익지 않은 토마토라면
        if (farm[k][i][j] === 0) {
          leftTomato += 1;
        }
      }
    }
  }

  // 저장될 때부터 모든 토마토가 익어있는 상태
  if (leftTomato === 0) {
    console.log(0);
    return;
  }

  let dayList = Array.from({ length: H }, () =>
    Array.from({ length: N }, () => Array.from({ length: M }, () => 0))
  );
  while (!queue.isEmpty()) {
    let [height, row, col] = queue.dequeue();

    for (const [D_HEIGHT, D_ROW, D_COL] of Object.values(DIR_OBJ)) {
      const NEW_HEIGHT = height + D_HEIGHT;
      const NEW_ROW = row + D_ROW;
      const NEW_COL = col + D_COL;

      // 인덱스가 주어진 범위를 벗어날 경우
      if (isValidIndex(NEW_HEIGHT, NEW_ROW, NEW_COL) === false) {
        continue;
      }
      // 이미 방문한 곳일 경우
      if (visited[NEW_HEIGHT][NEW_ROW][NEW_COL]) {
        continue;
      }
      // 이미 익은 토마토일 경우
      if (farm[NEW_HEIGHT][NEW_ROW][NEW_COL] === 1) {
        continue;
      }
      // 토마토가 없는 칸일 경우
      if (farm[NEW_HEIGHT][NEW_ROW][NEW_COL] === -1) {
        continue;
      }

      dayList[NEW_HEIGHT][NEW_ROW][NEW_COL] = dayList[height][row][col] + 1;
      leftTomato -= 1;

      // 토마토가 모두 익었을 경우
      if (leftTomato === 0) {
        console.log(dayList[NEW_HEIGHT][NEW_ROW][NEW_COL]);
        return;
      }

      queue.enqueue([NEW_HEIGHT, NEW_ROW, NEW_COL]);
      visited[NEW_HEIGHT][NEW_ROW][NEW_COL] = true;
    }
  }

  // 토마토가 모두 익지 못하는 상황
  console.log(-1);
}

solution(M, N, H, TOMATO_CONTAINER);
저작자표시 (새창열림)

'PS > 백준' 카테고리의 다른 글

백준 / 백트래킹 / 15683번 / 감시 / Java  (0) 2023.07.27
백준 / 그래프 / 2178번 / 미로 탐색 / JS  (0) 2023.04.28
백준 / 백트래킹 / 15654번 / N과 M (5) / JS  (0) 2023.04.01
백준 / 큐 / 1966번 / 프린터 큐 / JS  (2) 2023.03.24
    'PS/백준' 카테고리의 다른 글
    • 백준 / 백트래킹 / 15683번 / 감시 / Java
    • 백준 / 그래프 / 2178번 / 미로 탐색 / JS
    • 백준 / 백트래킹 / 15654번 / N과 M (5) / JS
    • 백준 / 큐 / 1966번 / 프린터 큐 / JS
    KimMinJun
    KimMinJun

    티스토리툴바