백준 2638 < 치즈 > JavaScript

2023. 2. 8.·☕️ 커리어 & 인터뷰 준비/코딩 테스트

📍문제 링크

https://www.acmicpc.net/problem/2638

 

2638번: 치즈

첫째 줄에는 모눈종이의 크기를 나타내는 두 개의 정수 N, M (5 ≤ N, M ≤ 100)이 주어진다. 그 다음 N개의 줄에는 모눈종이 위의 격자에 치즈가 있는 부분은 1로 표시되고, 치즈가 없는 부분은 0으로

www.acmicpc.net

 

📍알고리즘 분류

- 구현
- 그래프 이론
- 그래프 탐색
- 너비 우선 탐색
- 시뮬레이션
- 깊이 우선 탐색

 

📍문제 풀이

1과 0으로 이루어진 n * m 보드가 주어진다.

- 두 면이 0과 접한 1은 1턴 이후에 0으로 변하는데, 모든 1이 0으로 변하는데 몇 턴이 걸리는지 구하라

 

📍1트 : 완전탐색 -> 내부 공간 고려 못해 실패

1. 전체 보드 total 구하기

- total이 0이 아니면 반복

 

2. 중첩 for 문으로 board를 순회

- 1인 좌표에서 상하좌우 스캔

- 상 하 좌 우 스캔하여 0이면 cnt + 1

- cnt >= 2 이면 없앨 좌표로 저장

 

3. 반복문 끝나면 없앨 좌표 모두 0으로 바꿈 (중간 왜곡 방지 위해)

 

그런데.. 내부 공간을 생각 못해서 실패...

1이 아니라 0인 좌표에 dfs를 실행해야 한다..

 

📍2트 : 치즈(1인 원소)가 아닌 공기(0 인 원소)에 dfs 실행

- bfs 대신 dfs를 사용한 이유 (pop이 shift 보다 빠르니까.. 완전 탐색이니까 둘 다 상관없음)

 

1. 0인 원소에 dfs 실행

- 0이면 stack에 넣고

- 1이면 마지막에 위치 바꿀 좌표들의 배열에 넣어 저장

또, 2 이상 접촉 수를 가지기 위해 카운트

 

2. label을 사용하여 중첩 for 문을 한꺼번에 break

📍코드 (JavaScript)

const readline = require("readline");
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

const input = [];

rl.on("line", (line) => {
  input.push(line);
}).on("close", () => {
  const [N, M] = input.shift().split(" ").map(Number);
  const board = input.map((row) => row.split(" ").map(Number));
  let answer = 0;
  const getAreaVal = (nestedArr) => {
    return nestedArr
      .map((row) => row.reduce((acc, cur) => acc + cur, 0))
      .reduce((acc, cur) => acc + cur, 0);
  };

  // dfs 는 board를 수정하는 역할
  const dfs = (y, x) => {
    const stack = [[y, x]];
    const isVisited = Array.from({ length: N }, (_) =>
      Array.from({ length: M }, (_) => false),
    );
    const adjacentCntArr = Array.from({ length: N }, (_) =>
      Array.from({ length: M }, (_) => 0),
    );
    isVisited[y][x] = true;
    while (stack.length) {
      const [Y, X] = stack.pop();
      // 상하좌우 스캔하여 1이면 인접 카운트 배열에 +1
      // 0이면 미방이면 stack에 넣기
      // 상
      if (Y - 1 >= 0) {
        // 0이면 방문 표시하고 스택에넣기
        if (!board[Y - 1][X] && !isVisited[Y - 1][X]) {
          isVisited[Y - 1][X] = true;
          stack.push([Y - 1, X]);
        }
        // 1이면 인접 카운트 배열에 +1
        if (board[Y - 1][X]) {
          adjacentCntArr[Y - 1][X]++;
        }
      }
      // 하
      if (Y + 1 < N) {
        if (!board[Y + 1][X] && !isVisited[Y + 1][X]) {
          isVisited[Y + 1][X] = true;
          stack.push([Y + 1, X]);
        }
        if (board[Y + 1][X]) {
          adjacentCntArr[Y + 1][X]++;
        }
      }
      // 좌
      if (X - 1 >= 0) {
        if (!board[Y][X - 1] && !isVisited[Y][X - 1]) {
          isVisited[Y][X - 1] = true;
          stack.push([Y, X - 1]);
        }
        if (board[Y][X - 1]) {
          adjacentCntArr[Y][X - 1]++;
        }
      }
      // 우
      if (X + 1 < M) {
        if (!board[Y][X + 1] && !isVisited[Y][X + 1]) {
          isVisited[Y][X + 1] = true;
          stack.push([Y, X + 1]);
        }
        if (board[Y][X + 1]) {
          adjacentCntArr[Y][X + 1]++;
        }
      }
    }
    // 바꿀 좌표들을 찾아내면 0으로 바꿔줌
    for (let i = 1; i < N - 1; i++) {
      for (let j = 1; j < M - 1; j++) {
        if (adjacentCntArr[i][j] >= 2) board[i][j] = 0;
      }
    }
  };

  while (getAreaVal(board) > 0) {
    outer: for (let i = 0; i < N; i++) {
      for (let j = 0; j < M; j++) {
        if (!board[i][j]) {
          dfs(i, j);
          answer++;
          break outer;
        }
      }
    }
  }
  console.log(answer);
});

 

'☕️ 커리어 & 인터뷰 준비/코딩 테스트' 카테고리의 다른 글
  • 구간 합 (range sum) - 1. 누적 합 (prefix sum)
  • 백준 9935 < 문자열 폭발 > JavaScript
  • 백준 17073 < 나무 위의 빗물 > JavaScript
  • 백준 11497 < 통나무 건너뛰기 > JavaScript
지식물원
지식물원
지식이 자라는 식물원!
  • 지식물원
    지식물원
    지식물원
  • 전체
    오늘
    어제
    • 분류 전체보기 (510)
      • 🎨 프론트엔드 공부 (247)
        • JS & TS (86)
        • HTML & CSS (22)
        • React & Next (49)
        • Vue & Nuxt (22)
        • 기타 (68)
      • 🤓 기술 학습 & 공부 기록 (116)
        • Node.js (0)
        • Python (37)
        • 백엔드 (0)
        • 딥러닝 (1)
        • 컴퓨터 일반 (72)
        • 개발 인프라 (6)
      • 👨‍💻 프로젝트 경험 (6)
        • Work (0)
        • Toy (6)
      • ⚙️ 개발 팁 & 노하우 (21)
        • 프론트엔드 (6)
        • 기타 (15)
      • ☕️ 커리어 & 인터뷰 준비 (88)
        • 코딩 테스트 (88)
      • 📰 기술 트렌드 & 생각 정리 (4)
      • 📚 기타 (25)
        • 마케팅 (15)
        • 비개발서적 (10)
  • 블로그 메뉴

    • 태그
  • 링크

  • 공지사항

    • 모바일 접속 시 코드 하이라이팅 깨질 때
  • 인기 글

  • hELLO· Designed By정상우.v4.10.3
지식물원
백준 2638 < 치즈 > JavaScript
상단으로

티스토리툴바