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

Pythonでキャンディーゲームの勝敗を判定!プレイヤー1が最大スコアを獲得できるかチェックする方法


2人のプレイヤーがゲームを行う状況を考えてみましょう。一列に並んだ複数のキャンディーがあり、プレイヤー1には各キャンディーの点数を表す数値リスト nums が与えられます。各プレイヤーのターンでは、列の先頭から1個・2個・3個のいずれかの数だけキャンディーを取り除き、その合計点数を自分のスコアに加算します。すべてのキャンディーがなくなった時点でゲームは終了し、より高いスコアを獲得したプレイヤーが勝者となります。ここでは、プレイヤー1がこのゲームに勝てるかどうかを判定する方法を解説します。

たとえば、入力が nums = [1, 1, 2, 3, 50] の場合、出力は True になります。プレイヤー1が最初にキャンディーを1個だけ取ると、相手プレイヤーは必ず1〜3個のキャンディーを取ることになります。その結果、どのような展開になってもプレイヤー1が50点のキャンディーを確保できるためです。

アルゴリズムの手順

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

  • n := nums のサイズ
  • table := 0が3つ格納された配列
  • i を n−1 から 0 まで1ずつ減らしながら以下を繰り返す:
    • profit := −inf(負の無限大)
    • sum_val := 0
    • j を i から min(i + 3, n) まで繰り返す:
      • sum_val := sum_val + nums[j]
      • profit := profit と (sum_val − table[j − i]) のうち大きい方
    • table := [profit, table[0], table[1]] という3要素のリストに更新
  • table[0] > 0 なら true を返し、それ以外は false を返す

実装例

理解を深めるために、以下のPythonコードを見てみましょう。

import math
class Solution:
    def solve(self, nums):
        n = len(nums)
        table = [0, 0, 0]
        for i in range(n - 1, -1, -1):
            profit = -math.inf
            sum_val = 0
            for j in range(i, min(i + 3, n)):
                sum_val += nums[j]
                profit = max(profit, sum_val - table[j - i])
            table[:] = [profit, table[0], table[1]]
        return table[0] > 0
ob = Solution()
nums = [1, 1, 2, 3, 50]
print(ob.solve(nums))

入力

[1, 1, 2, 3, 50]

出力

True

アルゴリズムの仕組み

このソリューションは動的計画法(DP)を活用しています。table 配列は直近3ステップ分の「現在のプレイヤーと相手のスコア差」を保持しており、各位置 i において、1個・2個・3個のキャンディーを取るそれぞれの選択肢について「自分が獲得する合計点数から、その後相手が稼げる最大の差額を引いた値」を計算し、最も有利な選択を profit として記録します。最終的に table[0] が正であれば、先手のプレイヤー1が相手より高いスコアを確保できる、つまり勝利できることを意味します。

  1. Pythonで容量制限内に収まる品物の最大価値を求める方法(ナップサック問題の解法)

    問題の概要同じ長さを持つ2つのリスト「weights(重さ)」と「values(価値)」、そして容量を表す数値 k が与えられているとします。weights[i] と values[i] は、それぞれ i 番目の品物の重さと価値を表します。ここで、合計の重さが容量 k を超えない範囲で品物を選びます。ただし、各品物は1つしか選べないものとします。この条件のもとで、取得できる価値の合計の最大値を求めるのが目的です。これは動的計画法(DP)を使って解ける、いわゆる「0/1 ナップサック問題」の典型例です。入力例weights = [2, 3, 4]values = [2, 6, 4]capacit

  2. 文字列が空かどうかをチェックするPythonプログラム

    この記事では、与えられた文字列が空であるかどうかを判定するための解決策とアプローチについて解説します。 問題文 文字列が入力として与えられたとき、その文字列が空(空文字列)であるかどうかを判定する必要があります。 Pythonの文字列はイミュータブル(変更不可)な性質を持っているため、文字列に対して何らかの操作を行う際には注意して扱う必要があります。 ここでは、上記の問題を解決するための2つのアプローチを紹介します。 len()メソッドを使用する方法 等価演算子(==)を使用する方法 アプローチ1:len()メソッドを使う方法 len()関数で文字列の長さを取得し、その長さが0であれば空文