본문 바로가기

카테고리 없음

BOJ 게임 문제 스페셜

 최근 BOJ에 정체불명의 게임 문제들이 많이 추가되었다. 님 게임 문제뿐 아니라, 그리디하게 풀 수 있거나 자료구조를 이용하는 문제도 있고, 여러 모로 며칠간 재밌게 푼 것 같아 풀이를 정리해보려 한다. (이걸 쓰려고 티스토리 블로그도 개장했다. 이 글 다음 글은 몇 년 뒤에 올라올지 나도 잘 모르겠다.)


우선 이 문제들의 대부분을 풀기 위해서는 기초 지식으로 Sprague-Grundy Theorem, 혹은 '그런디 넘버'를 알아야 한다. 하지만 이 이론의 엄밀한 증명을 읽어 보기가 귀찮은 대다수의 분들을 위해, 간단히 필요한 부분만 추리면 아래와 같다. 수학적 배경은 나도 모르기 때문에 외워야 하는 부분만 뽑아 봤다. 만약 더 자세한 내용이 필요하신 분은 [위키 링크]를 참조하시길 바란다.


보통은 다음의 조건들을 만족하는 게임의 승자를 결정하는 문제가 그런디 넘버로 풀린다. (엄밀하지는 않은데 웬만하면 아래 조건을 만족하면 다 된다.)


  • 게임판의 상태가 주어졌을 때, 누구의 턴이든 관계없이 할 수 있는 행동의 집합이 동일해야 한다.
      • 예를 들어, 바둑의 경우엔 동일한 바둑판에서도 선공은 흑돌만, 후공은 백돌만 움직일 수 있기에 행동의 집합이 동일하지 않다.
  • 게임판의 상태에 사이클이 없어야 한다.
      • 50수 규칙이 없는 체스 게임이 있다고 하자. 이 게임에서는 흑과 백이 한 커맨드씩 두고, 그 다음턴엔 바로 전에 했던 행동을 undo하는 방식으로 무한히 같은 게임판을 반복시킬 수 있다.(둘 다 킹만 남은 상황을 생각해보자). 이처럼 사이클이 생길 수 있는 게임에서는 그런디 넘버의 사용이 힘들다.
  • 선공과 후공의 목표가 동일하다.
      • 이렇지 않은 게임이 문제로 나온다면 대부분 선공은 무언가를 최적화하려 하고, 후공은 그것을 방해하는 포지션을 맡는다. 이렇지 않고, 선공과 후공이 동일한 목표를 두고 경기하는 게임에서만 그런디 넘버를 사용해 보자.
      • 보통은 '더 이상 행동을 할 수 없는 플레이어가 패배한다' 가 조건이지만, 조금 변형하면 더 이상 행동할 수 없을 때 이길 수도 있다. 후자의 경우는 전자보다 조금 더 어렵다.

    이 조건들을 모두 만족하는 가장 간단한 게임으로는 '님 게임' 이 있다. 님 게임이 무엇인지는 [여기]에서 대충 확인하자. 하지만 아직 이걸 풀 수는 없으니 내용만 읽고 끄도록 하자.


    만약 위와 같은 게임이 있다면, 게임을 시작하는 순간 승패는 결정이 난다. 선공이 반드시 이기거나, 그럴 수 없다면 후공이 반드시 이긴다. 우리 목표는 이러한 게임들에서 선공과 후공 중 누가 이기는 지 알아내는 것이다.


    Grundy number란, 게임판의 각 상태별로 붙여 놓은 수를 말한다. 의미는 잘 모르겠으므로, 그냥 빨리 문제를 풀기 위해 grundy number가 어떻게 매겨지는지만 확인해 보자.


    • 먼저, 아무 것도 할 수 없는 게임판, 즉 게임이 끝난 게임판의 grundy number는 0이다. (by definition)
    • 그 이후는 귀납적으로 정의되는데, 만약 어떤 게임판에서 단 한 번의 행동으로 grundy number가 0, 1, ... , k인 게임판을 모두 방문할 수 있다면, 그러한 k 중 가장 큰 k에 대해 이 게임판의 grundy number는 k+1이다. 즉, 한 번의 행동으로 grundy number가 0인 게임판을 방문할 수 없다면, 바로 패배하는 게임판이 아니더라도 grundy number가 0인 것이다.

    예를 들어 위에 링크로 소개한 nim game에서는, 돌이 0개인 경우엔 아무 것도 할 수 없으므로 그런디 넘버가 0, 

    돌이 1개인 경우엔 0개인 상태로 보낼 수 있고, 0개인 게임판의 grundy number는 0이므로 이 게임판의 grundy number는 1,

    돌이 2개인 경우엔 돌이 0개, 1개인 상태로 보낼 수 있고, 각각의 grundy number가 0, 1이므로 돌이 2개인 게임판의 grundy number는 2가 된다.

    님 게임이 이러한 게임 중 가장 간단한 이유는, 보다시피 그냥 돌의 개수가 grundy number가 되기 때문이다.


    어떤 게임에 대해, 게임판 하나에서 선공이 이기는 조건은 grundy number > 0이면 된다. 엥? 그럼 돌이 0개만 아니면 선공이 이기나?

    실제로 그렇다. 그냥 시작하자마자 다 가져가면 끝이니까..

    하지만 님 게임은 이러한 게임판이 여러개 있는 경우가 대부분인데, 그런 경우엔 어떻게 승패를 결정할까? 예를 들면, 아까부터 예시로 들고 있는 님 게임에서는 돌무더기가 여러 개 있고, 각 돌무더기마다의 grundy number는 알고 있지만, 최종적으로 이 무더기를 모두 사용하는 게임에서 마지막 돌을 가져가는 승자가 누구인지는 바로 알기가 쉽지가 않다.


    답은 그냥 모든 게임판의 grundy number를 bitwise xor 연산하여, 그것이 0이 아니면 선공 승, 아니면 후공 승이다. 그냥 선공이 0으로 만들어 넘겨주면, 상대가 무엇을 하든 그런디 넘버의 총 xor이 다시 0이 되게 받아치는 방법이 존재하고(이 부분은 증명이 필요하나 적지 않는다), 언젠가 게임이 끝났을 때, 그 게임은 xor 값이 0인 상태임이 자명한데, 그 게임을 받은 사람이 상대방이기 때문이다. 즉, 내가 질 일이 없으므로 내가 이긴다. 좀 더 엄밀한 내용이 필요하면 더 자세히 쓰여 있는 블로그를 찾아보도록 하자.


    이제 위의 님 게임을 풀 수 있게 되었다! 그냥 주어지는 N개의 정수를 모두 xor 연산하여 0이 아니면 koosaga, 0이면 cubelover를 출력하면 정답이다. 혹시 제출해보고 싶다면 [여기]로.


    이제 이걸 외우고 나면(증명이 하나도 없으니 '이해한다' 라는 표현 대신 '외운다' 라는 표현을 사용했다), 새로 올라온 게임 문제들 중 반 정도가 넘는 수를 간단하게 풀어버릴 수 있다. 게임판을 정의하고, 모든 게임판에서 행동 한 번을 하여 grundy number를 모아서(재귀적으로 DP를 하면 된다) 처음 게임판들의 grundy number를 결정하고, 각 게임판의 grundy number를 xor해서 0보다 크면 koosaga, 0이면 cubelover가 이긴다고 생각하면 된다.


    아래는 각 문제에 대한 풀이이다. 문제 이름을 누르면 문제 링크로 가고, 풀이를 누르면 풀이가 열린다.

    <<<주의!>>>
    아래의 문제들은 대부분 풀이를 보면 재미가 확 떨어집니다. 위의 개념만 숙지했다면, 얼마든지 혼자 힘으로 풀 수 있는 문제가 대부분일 것입니다. 시도해보시고 정 안될 때만 참고자료로 열람해주세요!


    재미있는 숫자 게임


    핌버


    궁전 게임



    사실 이 뒤로 거의 모든 문제의 풀이를 적었었는데, 갑자기 블루스크린이 뜨더니 모든 글이 날아갔다.

    왜인지 임시저장 기능도 먹통이어서 전부 날려먹었는데, 다행히 크롬 탭 중 미리보기를 켜 뒀던 탭이 복구되어 거기서 복사해서 긁은 결과 위까지는 살렸다. 복사하는 과정에서 태그가 좀 깨진 것도 있을 텐데, 고치기 너무 귀찮고 지금 멘탈이 남아 있는 상태가 아니어서 그냥 진행하기로 한다.

    뒤 문제 풀이를 꽤 자세하게 적었었는데, 더 이상 자세히 쓸 여력이 없어 대강 쓰려고 한다. 궁금한 점이 있다면 댓글을..



    정말 너무 충격적이다. 요즘 블로그에 자동저장 기능이 없을 줄은 몰랐다. (있어도 제대로 안 되면 없는 거나 마찬가지다)

    크롬의 플래시 차단 규칙이 바뀌고 어쩌고 하던데, 지금은 임시저장 버튼을 눌러도 임시저장이 안 된다. 하하. 너무 좋은 기능


    하튼 시작한 김에 끝을 보기 위해 다시 달리기로 한다. 지속적으로 게시를 했다가 수정하는 방식으로 나만의 임시저장을 사용해야지.


    룩, 비숍, 킹, 나이트, 궁전 게임



    행렬 게임



    카드 게임



    대각 게임



    나이트 게임



    나누기 게임



    루트 님 게임



    루트 게임



    중복 없는 님 게임



    창업



    레몬 주스 게임(갓문제)



    소수 제곱 게임





    님 게임 3



    더일곱이 게임



    아인타 게임



    물건 넣기 게임



    채석장 게임



    이로써 모든 문제의 풀이를 다 작성했다!

    이 글을 보고 더 많은 사람들이 새로 추가된 게임 문제들을 시도해줬으면 좋겠다. 이 재미를 혼자 느끼기엔 조금 아쉽다.