목차

작은 정사각형

ps
링크acmicpc.net/…
출처BOJ
문제 번호1603
문제명작은 정사각형
레벨플래티넘 2
분류

게임 이론

시간복잡도O(M*(N+M))
인풋사이즈N<=10, M<=10
사용한 언어Python 3.11
제출기록34192KB / 76ms
최고기록76ms
해결날짜2023/06/25

풀이

코드

"""Solution code for "BOJ 1603. 작은 정사각형".

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

Tags: [Game theory]
"""

import functools
import itertools


EMPTY = '.'


@functools.cache
def compute_grundy(n):
    if n <= 1:
        return 0
    next_grundy_nums = {
        compute_grundy(i) ^ compute_grundy(n - i - 2) for i in range(n - 1)
    } | {compute_grundy(i) ^ compute_grundy(n - i - 1) ^ 1 for i in range(n)}
    return next(x for x in itertools.count() if x not in next_grundy_nums)


def main():
    for _ in range(3):
        # pylint: disable=unused-variable
        N, M = [int(x) for x in input().split()]
        board = [input() for _ in range(N)]

        tall_block_widths = []
        small_block_count = 0
        for row1, row2 in zip(board[::2], board[1::2]):
            for key, group in itertools.groupby(zip(row1, row2)):
                if key == (EMPTY, EMPTY):
                    tall_block_widths.append(len(list(group)))
                elif EMPTY in key:
                    small_block_count += len(list(group))
        if N % 2 == 1:
            small_block_count += board[-1].count(EMPTY)

        tot_grundy = small_block_count % 2
        for width in tall_block_widths:
            tot_grundy ^= compute_grundy(width)
        print('Y' if tot_grundy > 0 else 'M')


if __name__ == '__main__':
    main()