사탕 게임 (백준 3085)

2024. 4. 29. 17:48알고리즘

문제

상근이는 어렸을 적에 "봄보니 (Bomboni)" 게임을 즐겨했다.

가장 처음에 N×N크기에 사탕을 채워 놓는다. 사탕의 색은 모두 같지 않을 수도 있다. 상근이는 사탕의 색이 다른 인접한 두 칸을 고른다. 그 다음 고른 칸에 들어있는 사탕을 서로 교환한다. 이제, 모두 같은 색으로 이루어져 있는 가장 긴 연속 부분(행 또는 열)을 고른 다음 그 사탕을 모두 먹는다.

사탕이 채워진 상태가 주어졌을 때, 상근이가 먹을 수 있는 사탕의 최대 개수를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 보드의 크기 N이 주어진다. (3 ≤ N ≤ 50)

다음 N개 줄에는 보드에 채워져 있는 사탕의 색상이 주어진다. 빨간색은 C, 파란색은 P, 초록색은 Z, 노란색은 Y로 주어진다.

사탕의 색이 다른 인접한 두 칸이 존재하는 입력만 주어진다.

출력

첫째 줄에 상근이가 먹을 수 있는 사탕의 최대 개수를 출력한다.

예제 입력 1

3
CCP
CCP
PPC

예제 출력 1

3

예제 입력 2 

4
PPPP
CYZY
CCPY
PPCC

예제 출력 2

4

예제 입력 3

5
YCPZY
CYZZP
CCPPP
YCYZC
CPPZZ

예제 출력 3 

 

🚀문제 접근

  1. 모든 좌표에서 4방향 탐색을 해서 인접한 좌표를 찾는다.
  2. 그리고 인접한 좌표가 범위안에 존재하고, 색깔이 다른 경우에 두 좌표를 스왑한다.
  3. 두 좌표를 스왑한 후 모두 같은 색으로 이루어져 있는 가장 긴 연속 부분을 구한다.
  4. 그리고 스왑한 좌표를 원상복귀 시킨다.
let [n, ...maps] = require('fs').readFileSync(0).toString().trim().split('\n');
n = Number(n);
maps = maps.map((elem) => elem.trim().split(''));
const dy = [-1, 0, 1, 0];
const dx = [0, 1, 0, -1];
let ret = Number.MIN_SAFE_INTEGER;

function solution() {
  for (let i = 0; i < n; i++) {
    for (let j = 0; j < n; j++) {
      dfs(i, j);
    }
  }

  function dfs(y, x) {
    for (let i = 0; i < 4; i++) {
      const ny = y + dy[i];
      const nx = x + dx[i];
      if (ny < 0 || ny >= n || nx < 0 || nx >= n || maps[ny][nx] === maps[y][x]) continue;
      // swap
      let tmp = maps[ny][nx];
      maps[ny][nx] = maps[y][x];
      maps[y][x] = tmp;
      // 열 체크
      for (let i = 0; i < n; i++) {
        let prev;
        let cnt = 1;
        for (let j = 0; j < n; j++) {
          if (prev === maps[i][j]) cnt++;
          else {
          // 만약 연속부분이 끊겼다면 ret를 구하고 cnt를 초기화
            ret = Math.max(ret, cnt);
            cnt = 1;
          }
          prev = maps[i][j];
        }
        ret = Math.max(ret, cnt);
      }
      // 행 체크
      for (let i = 0; i < n; i++) {
        let prev;
        let cnt = 1;
        for (let j = 0; j < n; j++) {
          if (prev === maps[j][i]) cnt++;
          else {
            ret = Math.max(ret, cnt);
            cnt = 1;
          }
          prev = maps[j][i];
        }
        ret = Math.max(ret, cnt);
      }
      // re-swap
      tmp = maps[ny][nx];
      maps[ny][nx] = maps[y][x];
      maps[y][x] = tmp;
    }
  }

  return ret;
}

console.log(solution());

 

🎯막혔던 부분

스왑이 제대로 이루어지지 않았는데 이차원 배열의 요소를 string으로 받아왔기 때문에 스왑이 이루어지지 않았다.

["CCP", "CCP", "PPC"] ➡ [ ["C", "C", "P"], ["C", "C", "P"], ["P", "P", "C"] ] 이렇게 변경해야 스왑이 이루어진다.

 

그리고 CCCCPCCCP 에서 연속부분 중 가장 긴 값은 CCCC로 4가 나와야하지만 이전 코드에서는 7이 나왔다.

그 이유는 연속부분이 끊기는 시점에서 cnt를 초기화하고 max값을 구해야하지만 그러지 않았기 때문이다.

무조건 CCCCP 이런 식으로 입력값이 주어지는 줄 알고 실수를 했다.

'알고리즘' 카테고리의 다른 글

부등호 (백준 2529번)  (0) 2024.05.01
연산자 끼워넣기 (백준 14888)  (1) 2024.05.01
미세먼지 안녕! (백준 17144)  (0) 2024.04.23
인구 이동 (백준 16234)  (0) 2024.04.19
틱택토 (백준 7682)  (1) 2024.04.19