사용자 도구

사이트 도구


ps:problems:boj:25682

체스판 다시 칠하기 2

ps
링크acmicpc.net/…
출처BOJ
문제 번호25682
문제명체스판 다시 칠하기 2
레벨골드 5
분류

누적합

시간복잡도O(N*M)
인풋사이즈N<=2000, M<=2000
사용한 언어Python
제출기록192740KB / 2200ms
최고기록2200ms
해결날짜2022/11/17
태그

[단계]누적 합

풀이

  • 체스판 다시 칠하기를 확장시킨 문제. 체스판 다시 칠하기에서는 K가 8로 고정이었기 때문에, 단순하게 O(M*N*8*8) 알고리즘으로 충분했지만 여기에서는 조금 더 효율적인 알고리즘이 필요하다.
  • 사실 이 문제는 1차원 배열에서 고정된 길이의 부분배열들중 합이 최대가 되는 것을 찾는 문제를 2차원으로 확장시킨 문제이다.
  • 1차원이었으면, 슬라이딩 윈도우 방식으로 간단하게 구현할 수 있는 문제이지만, 2차원에서는 이 방식을 구현하는 것은 조금 번거롭다..
  • 대신 그냥 2차원 누적합을 계산해놓고, 이것을 이용해서 모든 부분구간에 대해서 부분합을 구하는 방식으로 구현했다. 메모리를 좀더 먹고, 속도도 살짝 느리겠지만 이쪽이 구현이 조금 더 간단했다. 어차피 빅오 시간복잡도는 O(NM)으로 동일하다.

코드

"""Solution code for "BOJ 25682. 체스판 다시 칠하기 2".

- Problem link: https://www.acmicpc.net/problem/25682
- Solution link: http://www.teferi.net/ps/problems/boj/25682

Tags: [prefix sum]
"""

import sys


def main():
    # pylint: disable=unused-variable
    N, M, K = [int(x) for x in sys.stdin.readline().split()]
    board = [sys.stdin.readline().rstrip() for _ in range(N)]

    prefix_sum = [[0] * (M + 1)]
    for row, psum_row_prev, target in zip(board, prefix_sum, 'BW' * N):
        psum_row_cur = [0]
        rsum = 0
        for ch, ps in zip(row, psum_row_prev[1:]):
            rsum += ch == target
            target = 'B' if target == 'W' else 'W'
            psum_row_cur.append(ps + rsum)
        prefix_sum.append(psum_row_cur)

    answer = K * K
    for beg, end in zip(prefix_sum, prefix_sum[K:]):
        for bb, be, eb, ee in zip(beg, beg[K:], end, end[K:]):
            s = ee - be - eb + bb
            answer = min(answer, s, K * K - s)

    print(answer)


if __name__ == '__main__':
    main()

토론

댓글을 입력하세요:
X Z X Q N
 
ps/problems/boj/25682.txt · 마지막으로 수정됨: 2022/11/18 01:57 저자 teferi