본문 바로가기

IT/Python

[백준] 14717번 앉았다 [Python]

728x90

 

 

1~10 숫자 카드 2벌, 총 20장의 카드
2장 중복 없이 뽑아서 같은 수면 땡, 다른 수면 끗 $($땡이 끗보다 더 강하다$)$
땡은 그 숫자 크기끼리 비교해서 큰 수가 더 강하고,

끗은 두 수의 합의 일의 자리 숫자가 크면 더 강하다.

내가 뽑은 숫자 두 장을 보고, 상대방의 카드는 모를 때, 내가 이길 확률을 구하는 문제

 

더보기

문제

섰다는 화투를 이용하여 20장의 카드를 가지고 2명 이상이 경기를 하는 게임이다.

이러한 섰다의 규칙을 단순화한 게임이 바로 '앉았다'이다.

앉았다의 규칙은 1, 2, 3, ... , 9, 10이 쓰인 카드가 각 2장씩 주어지며 총 20장의 카드가 사용되며, 2명이 참가한다.

다음은 앉았다의 경기 방법이다.

  1. 두 명의 참가자는 순서대로 20장의 카드 중 무작위로 2장의 카드를 가져온다.
  2. 상대방이 이미 가지고 간 카드를 중복해서 가져올 수는 없다. 그리고 자신은 어떤 카드를 가져왔는지 알 수 있지만, 상대방이 어떤 카드를 가져갔는지는 알 수 없다.
  3. 서로의 패를 공개한다.
  4. 강한 족보의 패를 가진 사람이 이긴다. 만약 두 참가자가 같은 족보의 패를 가졌다면 비긴다.

족보 $($위에 있는 족보일수록 더 강한 족보이다$)$

  • 10땡: 두 패가 모두 10
  • 9땡: 두 패가 모두 9
  • ...
  • 2땡: 두 패가 모두 2
  • 1땡: 두 패가 모두 1
  • 9끗: 땡이 아니고, 두 패를 더했을 때 일의 자리의 수가 9
  • 8끗: 땡이 아니고, 두 패를 더했을 때 일의 자리의 수가 8
  • ...
  • 1끗: 땡이 아니고, 두 패를 더했을 때 일의 자리의 수가 1
  • 0끗: 땡이 아니고, 두 패를 더했을 때 일의 자리의 수가 0

예를 들어, 영학이의 패가 1과 1이고, 상대의 패가 10과 9라고 하자.

그렇다면 영학이는 1땡이고, 상대는 9끗이다. 영학이가 더 강한 족보를 가졌으므로 영학이가 상대를 이긴다.

영학이는 자신이 어떤 패를 받았는지 보았고, 상대방의 패는 모르는 상태이다.

영학이는 영악해서 앉았다 게임에서 자신이 이길 확률이 높을 때만 돈을 베팅한다.

영악한 영학이를 위하여 영학이의 패가 입력으로 주어졌을 때 이길 수 있는 확률을 구하여라.

입력

영학이의 패를 뜻하는 두 개의 정수 A, B가 주어진다. $($1 ≤ A, B ≤ 10$)$

출력

영학이가 이길 확률을 소수점 이하 셋 째 자리까지 반올림해서 출력하시오.

반드시 뒤따르는 0도 출력해야 한다. 예를 들어, '0.700'을 출력했다면 정답이고, '0.7'을 출력했다면 오답이다.

14717번: 앉았다 $($acmicpc.net$)$

 

내가 20장 중에서 2장을 고른 상태이기 때문에 18장이 남았다.
상대방은 그 중에 2장을 고르는 경우의 수는 $_{18}C_{2} = \frac{18 \times 17}{2} = 153$가지이다.

1. 내가 고른게 땡이면 나보다 더 강한 땡의 개수=n를 세고,
2. 내가 고른게 끗이면 나보다 약한 끗의 개수=m를 세서 확률을 구함

1. 경우 확률: 1 - n/153

내가 뽑은 수가 a이면 n = 10 - a 이다.


2. 경우 확률: m/153
내가 뽑은 수가 a와 b이면, 20 장의 카드 중에 a와 b를 한 장씩 없앤 상태에서 가능한 모든 2장의 조합과 비교한다.
내가 끗이므로 서로 다른 두 장을 뽑는 경우에 두 숫자의 합의 일의 자리 숫자가 $(a+b)%10$보다 작은 경우의 수를 센다.

소수점 아래 세자리 수까지 출력하기 위해서
round로 소수점 셋째 자리수까지 반올림하고 
셋째짜리까지 안나오는 경우를 고려해서 format으로 소수점 셋째자리까지 출력하도록 했습니다.

처음에는 조합으로 구했습니다.

import sys
from itertools import combinations
a, b = map(int, sys.stdin.readline().split())
if a == b:
    print("{:.3f}".format(round(1-(10-a)/153, 3)))
else:
    li = list(range(1,11))*2
    li.remove(a)
    li.remove(b)
    a = (a+b)%10
    cb = combinations(li, 2)
    s = 0
    for c in cb:
        if c[0] != c[1] and sum(c)%10 < a:
            s += 1
    print("{:.3f}".format(round(s/153, 3)))

 

그런데 그냥 개수가 적어서 이중 for문으로 적었습니다.

import sys
a, b = map(int, sys.stdin.readline().split())
if a == b:
    print("{:.3f}".format(round(1-(10-a)/153, 3)))
else:
    li = list(range(1,11))*2
    li.remove(a)
    li.remove(b)
    a = (a+b)%10
    s = 0
    for i in range(18):
        for j in range(i+1, 18):
            if li[i] != li[j] and (li[i]+li[j])%10 < a:
                s += 1 
    print("{:.3f}".format(round(s/153, 3)))

 

더보기

예제 입력 1

1 1

예제 출력 1

0.941

예제 입력 2

1 2

예제 출력 2

0.275

예제 입력 3

1 9

예제 출력 3

0.000

예제 입력 4

10 10

예제 출력 4

1.000