# [Algorithm/JS] 백준 1018번 체스판 다시 칠하기

🔗 문제 바로가기 (opens new window)

# Question

지민이는 자신의 저택에서 MN개의 단위 정사각형으로 나누어져 있는 M×N 크기의 보드를 찾았다. 어떤 정사각형은 검은색으로 칠해져 있고, 나머지는 흰색으로 칠해져 있다. 지민이는 이 보드를 잘라서 8×8 크기의 체스판으로 만들려고 한다.

체스판은 검은색과 흰색이 번갈아서 칠해져 있어야 한다. 구체적으로, 각 칸이 검은색과 흰색 중 하나로 색칠되어 있고, 변을 공유하는 두 개의 사각형은 다른 색으로 칠해져 있어야 한다. 따라서 이 정의를 따르면 체스판을 색칠하는 경우는 두 가지뿐이다. 하나는 맨 왼쪽 위 칸이 흰색인 경우, 하나는 검은색인 경우이다.

보드가 체스판처럼 칠해져 있다는 보장이 없어서, 지민이는 8×8 크기의 체스판으로 잘라낸 후에 몇 개의 정사각형을 다시 칠해야겠다고 생각했다. 당연히 8*8 크기는 아무데서나 골라도 된다. 지민이가 다시 칠해야 하는 정사각형의 최소 개수를 구하는 프로그램을 작성하시오.

# Input

첫째 줄에 N과 M이 주어진다. N과 M은 8보다 크거나 같고, 50보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에는 보드의 각 행의 상태가 주어진다. B는 검은색이며, W는 흰색이다.

# Output

첫째 줄에 지민이가 다시 칠해야 하는 정사각형 개수의 최솟값을 출력한다.

# Example

# Input 1

8 8
WBWBWBWB
BWBWBWBW
WBWBWBWB
BWBBBWBW
WBWBWBWB
BWBWBWBW
WBWBWBWB
BWBWBWBW
1
2
3
4
5
6
7
8
9

# Output 1

1
1

# Input 2

10 13
BBBBBBBBWBWBW
BBBBBBBBBWBWB
BBBBBBBBWBWBW
BBBBBBBBBWBWB
BBBBBBBBWBWBW
BBBBBBBBBWBWB
BBBBBBBBWBWBW
BBBBBBBBBWBWB
WWWWWWWWWWBWB
WWWWWWWWWWBWB
1
2
3
4
5
6
7
8
9
10
11

# Output 2

12
1

# Input 3

8 8
BWBWBWBW
WBWBWBWB
BWBWBWBW
WBWBWBWB
BWBWBWBW
WBWBWBWB
BWBWBWBW
WBWBWBWB
1
2
3
4
5
6
7
8
9

# Output 3

0
1

더 많은 예제는 상단 url에서 확인

# Solution

문제의 요지를 잘 파악해야한다. 문제에서 체스판은 8x8이라고 했으므로 입력값으로 8x8보다 큰 보드를 받아오더라도 보드 내에서 수정횟수가 가장 적은 8x8 범위를 체크해야한다. 처음에 문제를 잘못 이해해서 입력값으로 받아온 체스판 크기 전체를 체크했었다.

입력값은 모든 공백을 제거하는 정규식을 통해 M, N, board 를 받아왔고, 맨 위 왼쪽 첫번째 칸이 흰색인 경우(white)와, 검은색인 경우(black) 를 라인을 분리하여 배열로 준비했다.

const fs = require('fs');
const [M, N, ...board] = fs.readFileSync('../input.txt').toString().trim().split(/\s+/);

const white = [
  'WBWBWBWB',
  'BWBWBWBW',
  'WBWBWBWB',
  'BWBWBWBW',
  'WBWBWBWB',
  'BWBWBWBW',
  'WBWBWBWB',
  'BWBWBWBW',
];
const black = [
  'BWBWBWBW',
  'WBWBWBWB',
  'BWBWBWBW',
  'WBWBWBWB',
  'BWBWBWBW',
  'WBWBWBWB',
  'BWBWBWBW',
  'WBWBWBWB',
];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  1. 입력받은 전체 보드판의 크기에서 8x8범위로 모든 경우의 수를 검사한다
  2. 8x8 범위의 수정이 필요한 칸 수를 찾아내는 함수

    보드판 칸을 white / black 보드와 비교했을 경우 수정해야할 횟수를 각 whiteCk / blackCk 변수에 저장한다.

  3. whiteCkblackCk 중 횟수가 적은 경우를 min 변수에 할당하여 최종적으로 최소 횟수를 출력한다.
// 1
for (let i = 0; i <= M - 8; i++) {
  for (let j = 0; j <= N - 8; j++) {
    check(i, j);
  }
}

// 2
function check(x, y) {
  let whiteCk = 0;
  let blackCk = 0;

  for (let i = x; i < x + 8; i++) {
    for (let j = y; j < y + 8; j++) {
      if (board[i][j] !== white[i - x][j - y]) whiteCk++;
      if (board[i][j] !== black[i - x][j - y]) blackCk++;
    }
  }
  let min = Math.min(whiteCk, blackCk); // 3
  if (min < result) result = min;
}
console.log(result);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 전체 풀이

const fs = require('fs');
const [M, N, ...board] = fs.readFileSync('../input.txt').toString().trim().split(/\s+/);
const white = [
  'WBWBWBWB',
  'BWBWBWBW',
  'WBWBWBWB',
  'BWBWBWBW',
  'WBWBWBWB',
  'BWBWBWBW',
  'WBWBWBWB',
  'BWBWBWBW',
];
const black = [
  'BWBWBWBW',
  'WBWBWBWB',
  'BWBWBWBW',
  'WBWBWBWB',
  'BWBWBWBW',
  'WBWBWBWB',
  'BWBWBWBW',
  'WBWBWBWB',
];

let result = 64;

for (let i = 0; i <= M - 8; i++) {
  for (let j = 0; j <= N - 8; j++) {
    check(i, j);
  }
}

function check(x, y) {
  let whiteCk = 0;
  let blackCk = 0;

  for (let i = x; i < x + 8; i++) {
    for (let j = y; j < y + 8; j++) {
      if (board[i][j] !== white[i - x][j - y]) whiteCk++;
      if (board[i][j] !== black[i - x][j - y]) blackCk++;
    }
  }
  let min = Math.min(whiteCk, blackCk);
  if (min < result) result = min;
}
console.log(result);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
Last Updated: 2022. 6. 5. 오후 3:42:39