AtCoder Beginner Contest 193 D – Poker をPython3で解く

Share

AtCoder上にある問題のうち、AtCoder Problemsでdiff 800以上と判定されているものを順番に解いていく企画。
基本的な考え方は全てコード中のコメントに入れてあるので、参照のこと。

出典:
AtCoder Beginner Contest 193 D – Poker

実装がなかなか難しい、というか面倒くさい問題。落ち着いて地道に書いていこう。

これをもうちょっと頑張れば、ポーカートーナメントの実況で出る、各プレイヤーの(その時々で計算される)勝利確率を出せそう……?

# AtCoder Beginner Contest 193 D - Poker
# https://atcoder.jp/contests/abc193/tasks/abc193_d
# tag: 二人ゲーム 確率 高橋君 青木君

# 幸い伏せられているカードは 1 枚ずつの計 2 枚。
# カードの種類も 9 種類しかないので、伏せられているカードの
# 組み合わせを全探索すればいい。

from collections import Counter
# とりあえず手札のリストから点数を求める関数を作っておく。
# 持ってない数も点数に入るので、問題文をちゃんと読んで書こう。
def get_score(cards):
    cnt = Counter(cards)
    result = 0
    for i in range(1, 10):
        if i not in cnt:
            result += i
        else:
            result += i * 10**cnt[i]
    return result

def main():
    K = int(input())
    hand_tak = [int(c) for c in input()[:-1]]
    hand_aok = [int(c) for c in input()[:-1]]

    # とりあえず表になっている枚数のカウント
    cnt = Counter(hand_tak + hand_aok)

    # 高橋君が勝つカードの引き方の通り数を求める
    tak_win_comb = 0

    # a, b が高橋君、青木君の伏せているカードとして、全探索。
    for a in range(1, 10):
        s_tak = get_score(hand_tak + [a])
        for b in range(1, 10):
            s_aok = get_score(hand_aok + [b])

            # 高橋君が勝つ場合
            if s_tak > s_aok:
                # 伏せられていたカードが異なるなら、
                # それぞれの残り枚数を掛けた通り数になる
                # 残りカードの枚数が足りないケースは、自動的に 0 通りに
                # なるので、場合分けは気にしなくていい。
                if a != b:
                    rest_a = K - cnt[a]
                    rest_b = K - cnt[b]
                    tak_win_comb += rest_a * rest_b
                # 同じカードが伏せられていた場合、
                # (残り枚数) * (残り枚数 - 1) 通りになる
                else:
                    rest_a = K - cnt[a]
                    tak_win_comb += rest_a * (rest_a - 1)
    
    # 伏せカードの全通り数は、9 * K 枚から 8 枚判明している状態からなので
    # (9 * K - 8) * (9 * K - 9) 通り。
    # これで割ったものが答えの確率になる。
    print(tak_win_comb / ((9 * K - 8) * (9 * K - 9)))

main()
Share

コメントを残す

メールアドレスが公開されることはありません。