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()