ちょうどの 金額を 払う 硬貨の 最少の枚数
- 動的計画法
- 問題 16
- やや難しい
- 目安 45 分
何種類かの
本番の
入力は
問題
ある
お釣りを
入力の形式
K X
c_1 c_2 ... c_K1 行目に
出力の形式
最少の
制約
- K は 1 以上 10 以下の整数です
- X は 1 以上 100000 以下の整数です
- c_i は 1 以上 100000 以下の
整数で、 どの 2 つも 違う額です
入力と出力の例
例 1
1 円、
入力
3 6 1 3 4
出力
2
例 2
2 円と
入力
2 7 2 4
出力
-1
ヒント
まだ開いていません
付箋は 3 枚。下の段ほど答えに近づきます
ヒント 2
ヒント 3答えに近い
全部の
先に
解答
best[a] を
Python
Python
import sys
data = sys.stdin.read().split()
k, x = int(data[0]), int(data[1])
coins = list(map(int, data[2:2 + k]))
INF = x + 1
best = [INF] * (x + 1)
best[0] = 0
for coin in coins:
for amount in range(coin, x + 1):
if best[amount - coin] + 1 < best[amount]:
best[amount] = best[amount - coin] + 1
print(best[x] if best[x] != INF else -1)JavaScript
JavaScript
const data = require("fs").readFileSync(0, "utf8").split(/\s+/).filter(Boolean).map(Number);
const k = data[0];
const x = data[1];
const coins = data.slice(2, 2 + k);
const INF = x + 1;
const best = new Array(x + 1).fill(INF);
best[0] = 0;
for (const coin of coins) {
for (let amount = coin; amount <= x; amount++) {
if (best[amount - coin] + 1 < best[amount]) best[amount] = best[amount - coin] + 1;
}
}
console.log(best[x] !== INF ? best[x] : -1);計算量
時間は O(K × X)、
遅い
大きい
よく ある間違い
- 大きい
硬貨から 使う 貪欲法で 答える。 例 1 のような 硬貨の 並びで外れます - 作れない
金額を 0 に して おき、 「0 枚で作れる」と 取り 違える。 作れない 印は 大きな 数 (X + 1 など ) にします - 作れない
ときに -1 ではなく、 表に 入れた 大きな 数を そのまま出力する - 金額 a を
大きい順に 回して、 同じ 硬貨を 1 枚しか 使えない 数え方に してしまう (それは 荷物を 1 つずつしか 選べない 問題の 書き方です) - 再帰で
書いて、 X が 10 万の ときに 深さの 上限で 止まる。 表を 小さい 金額から 順に 埋める 書き方なら、 深さの 心配は ありません
解答を動かした版 Python 3.12.14Node.js 22.23.4確認日 2026/10/31