目標: n個以上のりんごを最小コストで購入する
制約条件:
同期読み取りを使用することで、大きなファイルでもメモリ使用量を最小限に抑制。非同期処理のオーバーヘッドも回避。
なぜ n + max(x,y) - 1 で十分なのか?
例: n=4, x=2, y=5 の場合
maxApples = 4 + 5 - 1 = 8 → インデックス0〜8の9要素
maxApples = 4 + 5 - 1 = 8
dp = [0, ∞, ∞, ∞, ∞, ∞, ∞, ∞, ∞]
2個パック: dp[2] = min(∞, 0+110) = 110
5個パック: dp[5] = min(∞, 0+200) = 200
| りんご個数 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|---|---|---|---|---|---|---|---|---|---|
| 初期状態 | 0 | ∞ | ∞ | ∞ | ∞ | ∞ | ∞ | ∞ | ∞ |
| i=0処理後 | 0 | ∞ | 110 | ∞ | ∞ | 200 | ∞ | ∞ | ∞ |
| i=2処理後 | 0 | ∞ | 110 | ∞ | 220 | 200 | ∞ | 310 | ∞ |
| i=5処理後 | 0 | ∞ | 110 | ∞ | 220 | 200 | ∞ | 310 | 400 |
| 最終状態 | 0 | ∞ | 110 | ∞ | 220 | 200 | 310 | 310 | 400 |
2個パック購入:
dp[0+2] = dp[2] = min(∞, 0+110) = 110
5個パック購入:
dp[0+5] = dp[5] = min(∞, 0+200) = 200
2個パック追加購入:
dp[2+2] = dp[4] = min(∞, 110+110) = 220
5個パック追加購入:
dp[2+5] = dp[7] = min(∞, 110+200) = 310
2個パック追加購入:
dp[5+2] = dp[7] = min(310, 200+110) = 310
5個パック追加購入:
dp[5+5] = dp[8] = min(∞, 200+200) = 400
n=4の場合の候補:
答え: 200円
O(n × max(x, y))
O(n + max(x, y))
理論的最小サイズでメモリ使用量を削減
dp[i] === Infinity の状態をスキップして無駄な計算を回避
Math.min()で配列範囲外アクセスを防止
大きな入力でもメモリ効率的な読み取り
この動的計画法の解法は、貪欲法では解けない問題を効率的に解決します。
理由: 大きなパックを買うことで小さなパックを複数買うより安くなる場合があり、局所最適解では全体最適解にならないため。