じゃんけん(全探索)

問題

コンピュータと $ N $ 回じゃんけんをします。

コンピュータの出す手はあらかじめ分かっていて、“G”はグー“C”はチョキ“P”はパー を表します。

あなたが、$ N $ 回のじゃんけんで出した 指の本数の合計 がちょうど $ M $ 本になるようにじゃんけんをすると、最高で何回 じゃんけんに勝つことができるでしょうか。

解法・ソースコード

まず今回はじゃんけんの指の合計数を求める問題なので、順番は気にする必要がありません。

次に、じゃんけんで出せる指の合計数が決まっているので、パー(指5本)の回数が決まればチョキ(指2本)の回数が決まり、チョキの回数が決まればグー(指0本)の回数が決まります。

とういうことで、パーの出す回数について全探索を行えば解を導くことができます。

グー、チョキ、パーを自分が g, c, p 回、コンピュータが cnt_g, cnt_c, cnt_p 回出すとき、自分がじゃんけんに勝てる回数は最大で min (g, enemy_c) + min (c, enemy_p) + min (p, enemy_g) 回となります。

ただし次の2点に関して注意が必要です。

🔹 グーを出す回数がマイナスになっていない
🔹 指の本数が $ M $ 本になっている

[Google Colaboratory]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#--------- 入力例1 ----------
n,m =4, 7 # じゃんけん数、じゃんけんで出す指の数の合計
s = 'CGPC' # コンピュータの出すじゃんけんの手
#--------- 入力例2 ----------
# n,m =5, 10 # じゃんけん数、じゃんけんで出す指の数の合計
# s = 'GPCPC' # コンピュータの出すじゃんけんの手
#---------------------------
cnt_g, cnt_p, cnt_c = 0, 0, 0
for s1 in s:
if s1 == 'G':
cnt_g += 1
elif s1 == 'P':
cnt_p += 1
else:
cnt_c += 1

res = 0
for p in range(m // 5 + 1): # グーを出せる回数分ループ
c = (m - p * 5) // 2 # チョキの回数を求める
g = n - p - c # グーの回数を求める
if g < 0: # グーの回数がマイナスの場合パス
pass
elif p * 5 + c * 2 == m: # 指の合計本数が指定回数と同じ場合
x = min(cnt_g, p) + min(cnt_p, c) + min(cnt_c, g)
res = max(res, x)

print('解:', res)

[実行結果(入力例1)]

解:4

パーを1回、チョキを1回、グーを2回だすと、指の本数は全部で7本となり、最大4回 勝つことができます。

[実行結果(入力例2)]

解:3

パーを2回、チョキを0回、グーを3回だすと、指の本数は全部で10本となり、最大3回 勝つことができます。