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

Pythonで最大kステップ以内に最終インデックスへ到達するための最小コストを求めるプログラム

問題の概要

数値のリスト nums と整数 k が与えられているとします。nums[i] の各要素は、インデックス i に着地したときにかかるコストを表しています。プレイヤーはインデックス 0 からスタートし、nums の最後のインデックスを目指します。各ステップでは、現在いる位置 X から、最大 k ステップ先までの任意の位置へジャンプすることができます。

ゴールである最後のインデックスに到達するまでに支払うコストの合計を最小化したい場合、その最小値はいくつになるでしょうか?

入力例

たとえば、nums = [2, 3, 4, 5, 6]、k = 2 という入力が与えられたとします。このとき、出力は 12 になります。これは、インデックス 0・2・4 の位置にある 2 + 4 + 6 を選んで通過することで、合計コスト 12 という最小値が実現できるためです。

解法のアプローチ

この問題は動的計画法(DP)の考え方で解くことができます。各位置 i における最小累積コストは、「直近 k 個以内の位置の中で最小の累積コスト」に nums[i] を加えたものになります。しかし、毎回 k 個の候補をすべて調べると計算量が膨らんでしまうため、優先度付きキュー(ヒープ)を使って「到達可能な範囲内での最小コスト」を効率的に取り出せるようにします。

具体的には、以下の手順で処理を進めます。

  • ans := 0 として初期化する
  • h := 空のヒープを用意する
  • i を 0 から nums のサイズ未満まで繰り返す
    • val := 0 とする
    • h が空でない限り、次を繰り返す
      • [val, index] := ヒープの先頭要素 h[0]
      • index >= i - k であれば(まだジャンプ範囲内なら)、ループを抜ける
      • そうでなければ、範囲外になったのでヒープ h から先頭を削除する
    • ans := nums[i] + val と更新する
    • (ans, i) のペアをヒープ h に挿入する
  • 最後に ans を返す

ヒープには「その時点までの累積コスト」と「その位置のインデックス」をペアで格納するため、現在位置から k ステップ以内に届かなくなった古いエントリを自動的に排除しながら、常に有効な最小コストを参照できます。

実装例

それでは、実際のPythonコードを見て理解を深めましょう。

from heapq import heappush, heappop
class Solution:
   def solve(self, nums, k):
      ans = 0
      h = []
      for i in range(len(nums)):
         val = 0
         while h:
            val, index = h[0]
            if index >= i - k:
               break
            else:
               heappop(h)
         ans = nums[i] + val
         heappush(h, (ans, i))
      return ans

ob = Solution()
nums = [2, 3, 4, 5, 6]
k = 2
print(ob.solve(nums, k))

入力

[2, 3, 4, 5, 6], 2

出力

12

まとめ

このプログラムでは、ヒープ(優先度付きキュー)を活用することで、各位置への到達時に「直近 k ステップ以内の最小累積コスト」を高速に取得できます。計算量は O(n log n) となり、すべての経路を総当たりで調べる方法よりも大幅に効率的です。ジャンプ幅の制約があるコスト最小化問題において、ヒープによる範囲管理は非常に有用なテクニックといえます。

  1. Pythonで全ての点を接続するための最小コストを求めるプログラム

    問題の概要(x, y) の形式で表される複数の点が格納された配列 points があるとします。2つの点 (xi, yi) と (xj, yj) を接続するコストは、それらの間のマンハッタン距離として定義されます。マンハッタン距離は次の式で計算できます。|xi − xj| + |yi − yj|この問題では、すべての点を接続するために必要な最小のコストを求める必要があります。入力例points = [(0,0), (3,3), (2,10), (6,3), (8,0)]この場合、出力は 22 になります。これは、各辺の距離がそれぞれ 6 + 5 + 3 + 8 = 22 となるように点同士を接

  2. Pythonでチェスのナイトが目標位置に到達するまでの最小手数を求めるプログラム

    問題の概要 2つの値 r と c が与えられているとします。無限に広いチェス盤上で、ナイト(騎士)が最初に座標 (0, 0) に配置されているとき、そのナイトが位置 (r, c) に到達するまでに必要な最小の移動回数を求めます。 ナイトの動きは通常のチェスと同じで、「横に2マス・縦に1マス」または「縦に2マス・横に1マス」という移動を行います。 例えば、入力が r = 6、c = 1 の場合、出力は 3 となります。下図では、赤が初期位置、緑が最終位置、黄色が途中の経由地点を表しています。 解法のアプローチ この問題は、ナイトの移動パターンを数学的に分析することで、幅優先探索(BFS)の