[백준] 20024 - Bombs In My Deck (Python)

fortunetiger·2025년 7월 23일

BOJ

목록 보기
5/10
post-thumbnail

https://www.acmicpc.net/problem/20024

문제
동현이는 디지털 카드 게임을 하고 있다. 이 게임에서는 두 플레이어가 대전을 하며, 각 플레이어는 3030장의 카드로 구성된 카드 덱과 체력 포인트 3030점을 가지고 게임을 시작한다.
두 플레이어는 번갈아가며 자신의 카드 덱에서 카드를 뽑으며, 체력 포인트가 먼저 00점 이하가 되는 플레이어가 패배한다.
동현이는 이번에 꽤나 힘겨운 상대를 만났는데, 이 상대는 동현이의 카드 덱에 폭탄 몇 장을 심어버렸다. 이제 동현이의 카드 덱 AA장 속에는 BB장의 폭탄이 있다. 각 카드가 폭탄일 확률은 균등하다.
동현이의 다음 턴 시작 시점의 체력 포인트는 CC점이다. 다음 턴에 동현이는 카드 덱의 맨 윗장부터 한 장씩 카드를 뽑고, 폭탄이 아닌 카드가 뽑히거나 체력 포인트가 00점이 될때까지 이를 반복한다. 폭탄인 카드를 뽑으면 체력 포인트 55점이 깎인다. 동현이의 카드 덱에는 폭탄이 아닌 카드가 적어도 한 장 존재함이 보장된다.
동현이는 폭탄 카드 때문에 게임에서 패배할까봐 걱정하고 있다. 다음 턴에 동현이가 살아남을 확률을 계산해 동현이에게 알려주자.

입력
첫번째 라인에 공백으로 구분된 정수 AA, BB, CC가 주어진다. (11\leqBB<\ltAA\leq30,130, 1\leqCC\leq3030)
동현이의 카드 AA장 중 BB장은 폭탄이며, 현재 체력 포인트는 CC점이다.

출력
다음 턴에서 동현이가 살아남을 확률을 출력한다.
절대 오차는 10610^{-6}까지 허용한다.

1) 아이디어

  • 먼저 현재 체력 포인트 c를 바탕으로 최대 몇 장의 폭탄 카드를 뽑아도 되는지 계산한다. 0점 이하가 되면 패배하므로, c-1을 5로 정수 나눗셈한다. 예를 들어 현재 체력 포인트가 5점인 경우 폭탄 카드를 한 장만 뽑아도 패배하므로 k는 0이 된다(c//5로 계산하는 경우에는 이 상황이 패배 상황에 포함되지 않는다).
  • 폭탄이 아닌 카드를 뽑으면 턴이 종료되며, k장 이상의 폭탄 카드를 뽑으면 무조건 패배하므로 k+1장 이상의 카드를 뽑는 상황은 고려할 필요가 없다.
  • 현재 덱에 포함된 폭탄 카드 수(b)가 k보다 작은 경우에는 모든 폭탄 카드를 뽑아도 패배하지 않으므로 더이상 고려할 필요가 없다.
  • 이후 루프를 돌면서 뽑은 카드가 폭탄 카드일 때와 아닐 때로 나누어 정답에 더한 후 출력한다.

2) 풀이

kb보다 작거나 같은 경우에만 확률을 계산한다. 최종 출력할 ans와 이전까지 폭탄 카드를 뽑은 조건부확률 tmp를 각각 (a-b)/ab/a로 초기화하고(첫번째 카드 뽑기), k번 루프를 돈다.
anstmp를 선언할 때 첫번째 카드를 뽑았으므로 ab를 업데이트한다. 각 루프에서 ans에 더해지는 값은 폭탄이 아닌 카드가 m+1회에서 처음 나왔을 때의 조건부확률이다. 다음 라인에서 m+1번째에 폭탄 카드를 뽑을 확률을 tmp에 곱해 업데이트한다.

3) 정답 코드

a, b, c = map(int, input().split())
k = (c-1)//5

if b<k:
    print(1)
    
else:
    ans, tmp = (a-b)/a, b/a
    for m in range(k):
        a, b = a-1, b-1
        ans += tmp*(a-b)/a
        tmp *= b/a

    print(ans)

0개의 댓글