Python
 Computer >> コンピューター >  >> プログラミング >> Python

Pythonで「蓮と毛虫」ゲームの勝利に必要な期待手数を求めるプログラム

問題の概要

n行m列のグリッドを考えます。Amal(アマル)とBimal(ビマル)が、このグリッド上で次のようなルールのゲームを行います。

  • Amalは白い「蓮(ロータス)」のタイルを最上行の任意のマスに置き、Bimalは「毛虫(キャタピラー)」のタイルを最下行の任意のマスに置きます。
  • Amalが先手となり、交互に手番を進めていきます。
  • Amalは自分のタイルを、現在いるマスに隣接する8方向(縦・横・斜め)のいずれかのマスへ移動できます。
  • 一方、Bimalの毛虫タイルは、左右への移動またはその場にとどまることしかできません。

Amalの目的はできるだけ少ない手数でBimalを捕まえることであり、逆にBimalの目的はできるだけ長く逃げ続けることです。両者がそれぞれ配置する列をランダムに選んだ場合、Amalがこのゲームに勝つまでに必要となる手数の期待値を求めるのが本問題です。

例として、n = 5、m = 7 の場合、出力は 4.571428571428571 となります。

解法のアプローチ

この問題を解くには、以下の手順に従います。

  • r を 0 で初期化します。
  • l を 0 から m - 1 まで繰り返します。
    • temp := n - 1.0 とします。
    • l >= n の場合、temp に (l - n + 1) * ((l - 1) / m) を加算します。
    • l < m - n の場合、temp に (m - n - l) * ((m - l - 2) / m) を加算します。
    • r に temp / m を加算します。
  • 最後に r を返します。

実装例

理解を深めるために、以下のPythonによる実装例を見てみましょう。

def solve(n, m):
    r = 0

    for l in range(m):
        temp = n - 1.0
        if l >= n:
            temp += (l - n + 1) * ((l - 1) / m)
        if l < m - n:
            temp += (m - n - l) * ((m - l - 2) / m)
        r += temp / m

    return r

n = 5
m = 7
print(solve(n, m))

入力

5, 7

出力

4.571428571428571
  1. Pythonでi個のx、j個のy、k個のzからなる部分列の個数を求めるプログラム

    文字列 s が「x」「y」「z」で構成されているとします。このとき、「x」が i 個(i ≥ 1)、その後に「y」が j 個(j ≥ 1)、さらにその後に「z」が k 個(k ≥ 1)という順序で並ぶ部分列の総数を求めます。 例えば、入力が s = xxyz の場合、出力は 3 になります。これは xyz を2通りと xxyz を1通りの合計3通り作れるためです。 解き方のアプローチ この問題は動的計画法(DP)の考え方を使うと効率的に解けます。文字列を先頭から順に走査しながら、次の3つのカウンターを更新していきます。 x: それまでに見つかった「xのみで構成される部分列」の個数 y: そ

  2. Pythonでソート済みリストの重複を削除するゲームに必要なターン数を求めるプログラム

    問題の概要友人であるアマル(Amal)とビマル(Bimal)が、numsという名前のソート済み数値リストを使ってゲームを行っているとします。各ターンでは、まずアマルが任意の3つの数値を選び、次にビマルがそのうちの1つを削除し、続いてアマルがさらに1つを削除します。リストは最初、奇数個の要素で構成されています。ここで、アマルはリストから重複要素をなくすために必要なターン数を最小化したいと考え、一方ビマルはターン数を最大化しようとします。両者が最適な戦略で行動するとき、このゲームが完了するまでに必要なターン数を求めるのが課題です。入出力例例えば、入力が nums = [1, 1, 2, 3, 3,