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

Pythonでレンガ除去ゲームの最大スコアを求めるプログラム

アマルとビマルがゲームをしているとします。配列 nums は、上に番号が書かれた n 個のレンガを表しています。このゲームでは、プレイヤーは交互に山の上から1個、2個、または3個のレンガを取り除くことができ、取り除いたレンガに書かれた数字がそのプレイヤーのスコアに加算されます。常にアマルが先手であるとき、アマルが確保できる最大のスコアを求める必要があります。

例えば、入力が nums = [1,2,3,4,5] の場合、出力は 6 になります。アマルは最初に {1}、{1,2}、{1,2,3} のいずれかを取ることができます。もし最初に2個か3個をまとめて取ると、ビマルが残りをすべて取って最大のスコアを得てしまいます。しかし、アマルが最初に 1 だけを取れば、ビマルは最大でも {2,3,4} = 9 しか取れず、残った 5 をアマルが取ることができます。したがって、アマルの合計スコアは 1 + 5 = 6 となります。

解法のアプローチ

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

  • INF := 9999
  • n := nums のサイズ
  • リスト nums を反転する
  • temp := サイズ n の配列を作成し、0 で初期化する
  • total := サイズ n の配列を作成し、0 で初期化する
  • nums の各インデックス i と値 val に対して、次を実行する
    • total[i] := total[i-1] + val
  • temp[0] := nums[0]
  • temp[1] := temp[0] + nums[1]
  • temp[2] := temp[1] + nums[2]
  • i を 3 から n - 1 まで繰り返す
    • a := nums[i]
    • b := nums[i] + nums[i-1]
    • c := nums[i] + nums[i-1] + nums[i-2]
    • temp[i] := a, b, c の最大値
  • temp[n-1] を返す

この解法では、まずレンガの並びを反転させることで、配列の末尾が「山の一番上」に対応するようにしています。これにより、先手が選べる選択肢(末尾側から1〜3個の連続したレンガ)を動的計画法で評価しやすくなります。また、配列 total には累積和を格納しておき、任意の区間の合計を効率よく参照できるようにしています。最終的な答えは temp[n-1]、つまり山全体を見たときの先手(アマル)の最大スコアとなります。

実装例

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

INF = 99999
def solve(nums):
   n = len(nums)
   nums.reverse()
   temp = [0]*n
   total = [0]*n
   for i, val in enumerate(nums):
      total[i] = total[i-1] + val
   temp[0] = nums[0]
   temp[1] = temp[0]+nums[1]
   temp[2] = temp[1]+nums[2]
   for i in range(3, n):
      a = nums[i]
      b = nums[i] + nums[i-1]
      c = nums[i] + nums[i-1] + nums[i-2]
      temp[i] = max(a, b, c)
   return temp[n-1]

nums = [1,2,3,4,5]
print(solve(nums))

入力

[1,2,3,4,5]

出力

6
  1. Pythonで数値を削除して最大の加算スコアを求めるプログラム|区間DPによる解法

    問題の概要 数値のリスト nums が与えられます。次のような操作を考えます。 リストの先頭と末尾以外から数値を1つ選び、取り除きます。 その際、「選んだ数値 + 両隣の数値」の合計がスコアに加算されます。 この操作は、先頭と末尾を選ばない限り何度でも繰り返せます。 このとき、最終的に得られるスコアの最大値を求めるのが目的です。 入力例と動作の確認 入力が nums = [2, 3, 4, 5, 6] の場合、出力は 39 になります。手順は以下の通りです。 5 を選択:スコアは (4 + 5 + 6) = 15、配列は [2, 3, 4, 6] になります。 4 を選択:スコアは (

  2. Pythonで連続する部分配列の最大積を求めるプログラム

    nums という配列が与えられたとき、少なくとも1つの要素を含む「連続した部分配列」の中から、要素の積が最大になるものを見つけて、その積を返すことを考えます。例えば、配列が [1,9,2,0,2,5] の場合、連続する部分配列 [1,9,2] の積が最大となるため、出力は 18 になります。 解法のアプローチ この問題は動的計画法(DP)を使って効率的に解くことができます。ポイントは、負の数同士を掛けると正の数になる可能性があるため、各位置における「最大積」と「最小積」の両方を追跡することです。 具体的な手順は以下の通りです。 max_list:nums と同じサイズのリストを作成し、0で初