https://www.acmicpc.net/problem/25682
문제
지민이는 자신의 저택에서 MN개의 단위 정사각형으로 나누어져 있는 M×N 크기의 보드를 찾았다. 어떤 정사각형은 검은색으로 칠해져 있고, 나머지는 흰색으로 칠해져 있다. 지민이는 이 보드를 잘라서 K×K 크기의 체스판으로 만들려고 한다.
체스판은 검은색과 흰색이 번갈아서 칠해져 있어야 한다. 구체적으로, 각 칸이 검은색과 흰색 중 하나로 색칠되어 있고, 변을 공유하는 두 개의 사각형은 다른 색으로 칠해져 있어야 한다. 따라서 이 정의를 따르면 체스판을 색칠하는 경우는 두 가지뿐이다. 하나는 맨 왼쪽 위 칸이 흰색인 경우, 하나는 검은색인 경우이다.
보드가 체스판처럼 칠해져 있다는 보장이 없어서, 지민이는 K×K 크기의 체스판으로 잘라낸 후에 몇 개의 정사각형을 다시 칠해야겠다고 생각했다. 당연히 K×K 크기는 아무데서나 골라도 된다. 지민이가 다시 칠해야 하는 정사각형의 최소 개수를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 정수 N, M, K가 주어진다. 둘째 줄부터 N개의 줄에는 보드의 각 행의 상태가 주어진다. B는 검은색이며, W는 흰색이다.
출력
첫째 줄에 지민이가 잘라낸 K×K 보드를 체스판으로 만들기 위해 다시 칠해야 하는 정사각형 개수의 최솟값을 출력한다.
제한
- 1 ≤ N, M ≤ 2000
- 1 ≤ K ≤ min(N, M)
문제를 읽고 이전의 구간 합 구하기 5 의 응용 문제라는 것을 파악하였다.
그대로 적용하기만 하면 쉽게 풀 수 있을 거라 생각했지만, 특정 패턴을 찾는 데 시간이 많이 걸렸다.
우선, 체스 판 시작이 B인 경우와 W인 경우를 각각 구할 필요가 없다. 왜냐하면,
(바둑판의 전체 수 - B로 시작한 바둑판에서 W로 수정해야 하는 개수) = W로 시작한 바둑판에서 B로 수정해야 하는 개수
( (16 - 6) = 10 )가 성립하기 하여 한 가지 패턴의 수정해야 하는 개수를 구한 후 최소 값을 찾아주면 되기 때문입니다.
다음은 체스 판 시작이 B인 경우로 정하고, (1, 1) 부터 (i, j)까지 수정해야하는 판의 개수 합을 적은 표입니다.
패턴을 확인하면,
(i + j) 가 홀수일때는 체스판이 W여야 하는 경우 이며,
해당 체스판이 W이면, (i-1, j) + (i, j-1) - (i-1, j-1) / 아니면, (i-1, j) + (i, j-1) - (i-1, j-1) + 1을 합니다.
똑같이 (i + j)가 짝수일때는 체스판이 B여야 하는 경우이며,
해당 체스판이 B이면, (i-1, j) + (i, j-1) - (i-1, j-1) / 아니면, (i-1, j) + (i, j-1) - (i-1, j-1) + 1을 합니다.
이후 구해야하는 범위 K의 i, j 값을 확인하며,
(i, j) - (i - K, j) - (i, j - K) + (i - K, j - K) 의 최소값을 구합니다.
import sys
input = sys.stdin.readline
N, M, K = map(int, input().split()) # 행, 열, 크기
maps = [list(input().rstrip()) for _ in range(N)]
SUM = [[0] * (M+1) for _ in range(N+1)]
for r in range(1, N+1):
for c in range(1, M+1):
if (r + c) % 2 == 0:
if maps[r-1][c-1] == 'B':
SUM[r][c] = SUM[r-1][c] + SUM[r][c-1] - SUM[r-1][c-1]
else:
SUM[r][c] = SUM[r-1][c] + SUM[r][c-1] - SUM[r-1][c-1] + 1
else:
if maps[r-1][c-1] == 'W':
SUM[r][c] = SUM[r-1][c] + SUM[r][c-1] - SUM[r-1][c-1]
else:
SUM[r][c] = SUM[r-1][c] + SUM[r][c-1] - SUM[r-1][c-1] + 1
max_ = -float('inf')
min_ = float('inf')
for r in range(K, N+1):
for c in range(K, M+1):
max_ = max(SUM[r][c] - SUM[r-K][c] - SUM[r][c-K] + SUM[r-K][c-K], max_)
min_ = min(SUM[r][c] - SUM[r-K][c] - SUM[r][c-K] + SUM[r-K][c-K], min_)
print(min(min_, max_, K*K - min_, K*K - max_))
'Coding Test > 백준' 카테고리의 다른 글
[백준] / [Python] / [10986] 나머지 합 (0) | 2022.12.01 |
---|---|
[백준] / [Python] / [16139] 인간-컴퓨터 상호작용 (0) | 2022.12.01 |
[백준] / [Python] / [11660] 구간 합 구하기 5 (0) | 2022.11.30 |
[백준] / [Python] / [2559] 수열 (0) | 2022.11.28 |
[백준] / [Python] / [11659] 구간 합 구하기 4 (0) | 2022.11.28 |