2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

コインの組み合わせは何通り? 〜動的計画法〜

Last updated at Posted at 2019-07-22

コインの組み合わせは何通り? 〜動的計画法〜

問題:1枚あたりの価値が{2,3,5}の3種類のコインを組み合わせ、金額の合計をちょうど14にするやり方は何通りか。コインはそれぞれ何枚でも使ってよいとする。


coin = [2, 3, 5]
total = 14
def combinations(coin, total):
    dp = [int(i % coins[0] == 0) for i in range(total + 1)]
    for coin in coin[1:]:
        for i in range(coin, total+1):
            dp[i] += dp[i-coin]
    return dp[-1]

コード解説

この例だと、まず価値が2のcoinだけを使った場合の場合の数を、全ての金額で算出する(これは単に2で割ってmod0の場合は0、mod1の場合は1)

この時点でのdpテーブルは以下のようになる。


[1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]

次に、「3を少なくとも1枚を使ってちょうど10を作る組み合わせ総数」をDPテーブルの数値に足し合わせていく。

例として、DPテーブルのtotal=10の数値を更新する場合を考える。
その時点でtotal=10の場所に入っている数値は「2だけを使ってちょうど10を作る組み合わせ総数」である。
ここに「3を少なくとも1枚を使ってちょうど10を作る組み合わせ総数」を加えた値は、「2と3を使ってちょうど10を作る組み合わせ総数」である。

ここで、「3を少なくとも1枚を使ってちょうど10を作る組み合わせ総数」は「2と3を使って7を作る組み合わせ総数(3は使っても使わなくても良い)」と同じであることに(天啓によって)気づく。

左から順々にDPテーブル更新していくため、totalが1から9の場合の数は既に更新されている(既に2と3を使ってちょうど{1~9}を作る組み合わせ総数が記入されている)と考えると、DP更新時にtotal=10に既に記入されている数値(2だけを使ってちょうど10を作る組み合わせ総数)にtotal=7に記入されている数値(2と3を使って7を作る組み合わせ総数)を足せばいい。

この要領で、DPテーブルのそれぞれを更新していくことをcoinを1枚ずつ増やしながら繰り返すと、最後には全コインを使った組み合わせ総数が求まる。(この時、range(coin, total-1)とcoinの数値始まりにしておくとインデックスエラーにならない)

以下が、DPの全ての更新が終了した後のテーブルである。
これらが、{2,3,5}を足してちょうど{1~14}を作る組み合わせ総数である。

[1, 0, 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6]
2
4
8

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?