Tesseractjh
한 걸음씩
Tesseractjh
전체 방문자
오늘
어제
  • 전체 (293)
    • IT (30)
      • JavaScript (7)
      • TypeScript (5)
      • React (5)
      • Next.js (3)
      • MongoDB (2)
      • Webpack (2)
      • HTML & CSS (1)
      • Git (0)
      • AWS (1)
      • 기타 (4)
    • 연습장 (259)
      • 백준(BOJ) 문제풀이 (185)
      • 프로그래머스 문제풀이 (61)
      • LeetCode 문제풀이 (2)
      • HackerRank 문제풀이 (7)
      • 낙서장 (3)
      • 기타 (1)
    • 프로젝트 (3)
      • 지뢰피하기 (1)
      • 키릴-라틴 문자 변환기 (1)
      • Flex & Grid (1)
    • 멋쟁이사자처럼 프론트엔드 스쿨 1기 (1)
      • 일기 & 회고록 (1)

인기 글

티스토리

hELLO · Designed By 정상우.
Tesseractjh

한 걸음씩

[백준 14500 - Node.js] 테트로미노
연습장/백준(BOJ) 문제풀이

[백준 14500 - Node.js] 테트로미노

2022. 10. 21. 16:09

🔗 문제 링크

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

 

14500번: 테트로미노

폴리오미노란 크기가 1×1인 정사각형을 여러 개 이어서 붙인 도형이며, 다음과 같은 조건을 만족해야 한다. 정사각형은 서로 겹치면 안 된다. 도형은 모두 연결되어 있어야 한다. 정사각형의 변

www.acmicpc.net

✏️ 풀이

const [[N, M], ...paper] = require('fs')
  .readFileSync('/dev/stdin')
  .toString()
  .trim()
  .split('\n')
  .map(v => v.split(' ').map(Number));

const maxValue = paper
  .reduce(
    (acc, row) => 
    	Math.max(acc, row.reduce((acc, v) => Math.max(acc, v), 0)),
    0
  );
const offset = [[0, 1], [0, -1], [1, 0], [-1, 0]];
const visited = [...Array(N)].map(() => Array(M).fill(false));
let maxSum = 0;

const dfs = (x, y, count, sum) => {
  if (sum + (4 - count) * maxValue <= maxSum) {
    return;
  }

  if (count === 4) {
    maxSum = Math.max(maxSum, sum);
    return;
  }

  for (const [dx, dy] of offset) {
    const nx = x + dx;
    const ny = y + dy;
    if (nx >= 0 && nx < N && ny >= 0 && ny < M && !visited[nx][ny]) {

      if (count === 2) {
        visited[nx][ny] = true;
        dfs(x, y, count + 1, sum + paper[nx][ny]);
        visited[nx][ny] = false;
      }

      visited[nx][ny] = true;
      dfs(nx, ny, count + 1, sum + paper[nx][ny]);
      visited[nx][ny] = false;
    }
  }
};

for (let i = 0; i < N; i++) {
  for (let j = 0; j < M; j++) {
    visited[i][j] = true;
    dfs(i, j, 1, paper[i][j]);
    visited[i][j] = false;
  }
}

console.log(maxSum);

테트로미노 각 도형의 모양은 ㅗ, ㅓ, ㅏ, ㅜ 모양을 제외하고는 모두 DFS로 4번 탐색해서 나오는 모든 경우와 같다. ㅗ, ㅓ, ㅏ, ㅜ의 경우 DFS를 세 번 시행한 후에 ㅣ, ㅡ, ㄴ, ㄱ 와 같은 모양이 되므로 여기서 절대로 DFS로는 이동경로가 ㅗ, ㅓ, ㅏ, ㅜ가 되도록 이동할 수 없다. 따라서 DFS로 4번 탐색하여 나오는 모든 경우 + ㅗ, ㅓ, ㅏ, ㅜ인 경우에 대해서 최댓값을 구하면 된다.

 

종이 위의 모든 좌표에 대해 DFS를 하여 모든 경우를 탐색한다. 탐색을 4번째 할 때마다 기존의 합의 최댓값과 비교하여 갱신한다. 탐색을 2번째 할 때마다 추가로 DFS를 한 번 더 실행하는데, 이 때 세 번째로 이동할 좌표를 탐색한 것으로 간주(visited[nx][ny] = true)하고 그냥 원래의 좌표(x, y)에서 다시 DFS를 실행한다. 이렇게 하면 두 개의 좌표만 탐색한 상태에서 두 번째 좌표에서 이동할 수 있는 4방향 중 한 곳을 방문 처리 후, 다른 좌표를 탐색하게 되는데 이렇게 하면 한 좌표에서 두 개의 방향을 탐색하면서 자연스럽게 ㅗ, ㅓ, ㅏ, ㅜ 모양을 커버할 수 있게 된다.

 

DFS가 수행시간이 오래 걸리므로 최적화를 위해 미리 종이 위의 좌표에 적힌 숫자 중 최댓값을 구하고, 매 DFS마다 앞으로 남은 탐색해야 할 좌표가 모두 이 최댓값이라고 가정했을 때 maxSum을 갱신할 수 있는지 여부(sum + (4 - count) * maxValue <= maxSum)를 먼저 판단하여 불가능하다고 판단되면 미리 DFS를 중단시키도록 하였다. 이렇게 하니까 수행시간이 2.5배 이상 빨라졌다.

저작자표시 비영리 (새창열림)

'연습장 > 백준(BOJ) 문제풀이' 카테고리의 다른 글

[프로그래머스 Level 2] 영어 끝말잇기 - JavaScript  (0) 2022.11.19
[백준 3190 - Node.js] 뱀  (0) 2022.10.23
[백준 6064 - Node.js] 카잉 달력  (0) 2022.10.19
[백준 1107 - Node.js] 리모컨  (1) 2022.10.14
[백준 2110 - Node.js] 공유기 설치  (0) 2022.10.13
    '연습장/백준(BOJ) 문제풀이' 카테고리의 다른 글
    • [프로그래머스 Level 2] 영어 끝말잇기 - JavaScript
    • [백준 3190 - Node.js] 뱀
    • [백준 6064 - Node.js] 카잉 달력
    • [백준 1107 - Node.js] 리모컨
    Tesseractjh
    Tesseractjh
    바닐라 자바스크립트를 좋아하는 개발자입니다

    티스토리툴바