2


5

各金種が無限の数のコインを持つコインチェンジ問題のためのアルゴリズムのアイデアを知りたいです。 DPを適用する方法を意味します(標準的な硬貨の変更問題のように)例えばセット1,10,15では、35のための変更は与えます - 10の2コインと15の1コイン

また、このための強引な強制アルゴリズムのアイデアを教えてください。 私はすべての集合を反復することを知っています。 しかし、ブルートフォースしながら各コインの数を変える方法

5 Answer


7


私は、解決策を一度に1ステップずつ、帰納的に構築することを考えます。

利用可能なコインは1c、5c、10c、25cです(あなたはあなたのニーズに応じてそれらを微調整することができます)

  1. 1c = 1 X 1cの最小コイン。 4セントまで、それが最小の宗派であるので、我々は1cのコインを必要とします。

  2. 5セントの場合、5cコインが1つあります。 それを上記の4cと組み合わせると、1から9までの任意の数を生成できます。

  3. 10セントの場合、1 X 10cが必要です。 上記の3つを組み合わせると、1から19までの任意の数を生成できます。

  4. 20は10で割り切れるので、20cでは、2 x 10cが必要です。

帰納的に問題を定式化することができれば、それに取り組む方が簡単かもしれません。

*編集:*さて、これは動的計画法の解決策を説明するための別の試みです。

x`行( x`は個別の宗派の数)と n`列( n`は最少の宗派を使用して構築する必要がある量)を持つテーブルを考えてください。 この表のすべてのセルは個別のサブ問題を表しており、最終的にはそれに対する解決策を含みます。 と仮定します。

行1は集合 {1c}`を表します。 1行目では無限の `1c`を使うことが許されています。2行目ではセットの{1c、10c}を表しています。つまり、2行目では無限の 1c`を行ないます。 、15c} `など 各列は、構築したい金額を表します。

したがって、すべてのセルは1つの小さな副問題に対応します。 例えば(簡単のためにインデックスは1から始まります)、 cell(1、5) =⇒ {1c} cell(2、9) =⇒構文だけを使って 5c`を構築します{1c、10c}` cell(3、27) =⇒ {1c、10c、15c}`を使って `27c`を構築する今、あなたの目的は cell(x、)への答えを得ることですn) `

解決策:`最も簡単な問題からテーブルの解決を始めましょう。 最初の行を解くのは簡単です。最初の行で利用可能な唯一の宗派は `{1c}`だからです。 1行目のすべてのセルは簡単な解を持ち、 `cell(1、n) = {nx1c}n`の 1c`のコイン)となります。

次の行に進んでください。 2行目を一般化して、(たとえば) `cell(2、28)`の解き方を見てみましょう。 `{1c、10c}`を使って `28c`を構築します。 ここでは、「10c」をソリューションに含めるかどうか、そしてコインの数を決める必要があります。 3つの選択肢があります(3 = 28/10 1)

選択1:前の行(` cell(1、18) に格納されている)の残りの部分を{1x10c}とします。 これはあなたに `{1x10c、18x1c} = `19コイン`を与える

選択2:` {2x10c} とそれ以前の行の残り( cell(1、8) に格納されている) これはあなたに `{2x10c、8x1c} = `10コイン`を与える

選択310c`と前の行の残り( cell(1、28) に格納されている)を取りません。 これはあなたに `{28x1c} = `28コイン`を与える

明らかに、選択肢2はコインの消費量が少ないので最適です。 テーブルに書き留めて先に進みます。 テーブルは、一度に1行ずつ、行内で、金額の大きい順に埋められます。

上記の規則に従って、あなたは cell(x、n)`に達するでしょう、それに対する解決策は `n / p 1`の選択肢の間での選択となる、ここで p`は行 `x`の最も新しい宗派です。 最良の選択はあなたの答えです。

この表は実際には小さな問題に対する解決策を記憶しているため、何度も解決する必要はありません。


3


ブルートフォース部分について:

int i、j、k。 for(i = 0; i <35; i){(for(j = 0; j <4; j){(for(k = 0; k <3; k)) == 35){//これはあなたが必要なものですか? // minimum = min(minimum、(i j k)); }}}}


0


総当たりについて。

それは「貪欲なアルゴリズム」と呼ばれます - あなたはいつもあなたが表す必要がある価値より大きくない最も大きいコインを取ります。

疑似コード。無限の回数をそれぞれ使用できる場合は、値を表すのに必要なコインの数を返します。

int [] greedy(int値、int []コイン){int [] ans = ...; int v = coins.length  -  1; int left = value; while(left> 0) ans://表現はできません。 }

疑似コード。無限の回数をそれぞれ使用できる場合は、値を表すのに必要なコインの数を返します。

int f(int value、int [] coins){int [] memo = new int [value 1]; Arrays.fill(memo、1234567); memo [0] = 0。 for(int coin:coins)for(int i = 0; i coin <= value; i)memo [i coin] = min(memo [i coin]、memo [i] 1);メモ[値]を返します。 }

どのコインを取るかを知るには、最後から始めます: if memo [value] = 3`なら、すべてのコインを調べて memo [value - coin] == 2`のように、 `(value - から続きます)を見つけます。 coin) `0になるまで


0


これは、ある番号体系から別の番号体系に番号を変換する方法です。 例えば:

35 = 1 * 2 ^ 5 0 * 2 ^ 4 0 * 2 ^ 3 0 * 2 ^ 2 0 * 2 ^ 1 1 * 2 ^ 0

あれは:

var cash = 35。 var coins = [15、10、5、1]; var change = {}; (var i = 0; iの場合


0


あなたはここでそれを実行することができますhttp://www.exorithm.com/algorithm/view/coin_change

関数coin_change($ amount、$ coins){$ change = array(); rsort($コイン) ($ i = 0; $ iの場合