사용자 도구

사이트 도구


ps:problems:boj:9079

동전 게임

ps
링크acmicpc.net/…
출처BOJ
문제 번호9079
문제명동전 게임
레벨실버 4
분류

BFS

시간복잡도O(T)
인풋사이즈T<=10
사용한 언어Python
제출기록33680KB / 156ms
최고기록60ms
해결날짜2022/01/21

풀이

  • 그냥 단순하게 현재 상태에서부터 BFS를 돌려서 모두 앞면인 상태나 모두 뒷면인 상태까지 가는데 필요한 최소 연산 횟수를 찾으면 된다.
  • 상태를 비트마스크로 표현하면, 세개의 동전을 뒤집는 연산은, 1이 세개 포함된 마스크와 xor하는 것으로 간단히 구현할 수 있다.
  • 상태의 갯수는 2^9이고, 각 상태에서는 8개의 연산이 가능하므로, BFS의 시간 복잡도는 O(V+E) = O(2^9 + 2^9*8) 이지만, 어차피 상수이므로 결국은 O(1)로 취급한다.
  • 매 테스트 케이스마다 주어진 상태에서 시작하는 BFS를 돌리면 총 T번의 BFS가 필요하다. 그것보다는 맨 처음에 모두 앞면인 상태에서 출발하는 BFS를 한번만 돌리면, 모든 상태들이 모두 앞면으로 바뀌기 위해서 얼마의 연산이 필요한지를 구할수 있다. 그러면 각 테스트케이스에 대해서는 그 구해놓은 값을 바로 사용하기만 하면 된다.
    • 정답을 구하기 위해서는 처음 상태에서 모두 뒷면인 상태로 바꾸기 위한 연산 횟수도 필요하다. 하지만 이는, 처음 상태를 전부 플립한 상태를 만들어서, 그 상태에서 모두 앞면인 상태로 바꾸는 것과 동일하다. 그렇기 때문에 모두 앞면인 상태에 대해서 구한 값을 그대로 활용할 수 있다.
  • 이렇게 하면 총 시간 복잡도는 O(T)가 된다.

코드

"""Solution code for "BOJ 9079. 동전 게임".

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

Tags: [BFS]
"""

from teflib import search

FLIP_MASKS = (0b111000000, 0b000111000, 0b000000111, 0b100100100, 0b010010010,
              0b001001001, 0b100010001, 0b001010100)
INF = float('inf')


def main():
    dists = search.min_distances(lambda x: [x ^ m for m in FLIP_MASKS],
                                 0b000000000)
    T = int(input())
    for _ in range(T):
        board = [input() for _ in range(3)]
        coins = ' '.join(board).split()
        state = sum(1 << i for i, ch in enumerate(coins) if ch == 'H')
        flipped_state = state ^ 0b111111111
        answer = min(dists.get(state, INF), dists.get(flipped_state, INF))
        print('-1' if answer == INF else answer)


if __name__ == '__main__':
    main()

토론

댓글을 입력하세요:
M F O U X
 
ps/problems/boj/9079.txt · 마지막으로 수정됨: 2022/01/21 15:22 저자 teferi