[boj] 14500. 테트로미노 (node.js)

호이·2022년 6월 18일
0

algorithm

목록 보기
76/77
post-thumbnail

문제

[boj] 14500. 테트로미노 (node.js)

  • 문제에서 제시된 4칸짜리 테트로미노를 대칭, 회전까지 포함해서 활용할 때, 포함하는 숫자의 총합이 최대가 되게끔 테트로미노를 위치시키려 한다. 이때 위치에 적힌 값의 총합을 구하는 문제다.

풀이

  • 문제에서 제시한 테트리미노는 대칭, 회전하는 경우까지 포함한다. 이는 곧 1*1 4칸으로 만들어낼 수 있는 모든 조합과 같다. 따라서 DFS, BFS를 활용해서 4칸짜리 탐색을 구현한다.
  • DFS는 visited 배열을 활용해서 4칸이 될 수 있는 경우 그 자리에 적힌 수들의 총합을 갱신한다. 이때 visited 반환하게 되는 경우 visited 여부를 지워줘야 한다는 점에 유의하자.
  • BFS는 DFS를 visited 배열을 활용해 구현했기 때문에 만들 수 없는 모양인 'ㅓ' 모양 테트로미노를 확인해보고 결과를 갱신하기 위한 함수다. 상하좌우 네 가지 방향 중 하나의 방향만을 제외하고 모두 거리를 1만큼 전진시킨 후 합을 갱신한다.

전체 풀이

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

const dir = [
  [-1, 0],
  [0, 1],
  [1, 0],
  [0, -1],
];

const solution = () => {
  const [N, M] = input().split(" ").map(Number);
  const dist = 4;
  const arr = [];
  for (let i = 0; i < N; i++) arr[i] = input().split(" ").map(Number);
  let result = 0;
  let visited = [];

  for (let i = 0; i < N; i++) {
    for (let j = 0; j < M; j++) {
      for (let k = 0; k < N; k++) visited[k] = [];
      visited[i][j] = 1;
      dfs(i, j, 0, arr[i][j]);
      bfs(i, j);
    }
  }
  return result;

  function dfs(r, c, k, sum) {
    if (k + 1 === dist) {
      result = Math.max(result, sum);
      return;
    } else {
      for (let i = 0; i < 4; i++) {
        const nr = r + dir[i][0];
        const nc = c + dir[i][1];
        if (nr < 0 || nc < 0 || nr >= N || nc >= M) continue;
        if (visited[nr] && visited[nr][nc]) continue;
        if (!visited[nr]) visited[nr] = [];
        visited[nr][nc] = 1;
        dfs(nr, nc, k + 1, sum + arr[nr][nc]);
        visited[nr][nc] = 0;
      }
    }
  }

  function bfs(r, c) {
    for (let i = 0; i < 4; i++) {
      let sum = arr[r][c];
      for (let j = 0; j < 4; j++) {
        if (i === j) continue;
        const nr = r + dir[j][0];
        const nc = c + dir[j][1];
        if (nr < 0 || nc < 0 || nr >= N || nc >= M) break;
        sum += arr[nr][nc];
      }
      result = Math.max(result, sum);
    }
  }
};

let _line = 0;
const input = () => stdin[_line++];

let stdin = [];
rl.on("line", function (line) {
  stdin.push(line);
}).on("close", function () {
  console.log(solution());
  process.exit();
});
profile
매일 부활하는 개복치

0개의 댓글