為替の変更

タイトル:コインの異なる宗派や金額の合計額の与えられたコイン。私たちは、合計金額を構成するために必要なコインの最小数を計算するための関数を書くことができます。コインの合計金額のいずれかで構成することができない組み合わせがない場合、-1を返します。
例:
例1:

入力:コイン= [1、2、 5]、量= 11
出力:3

説明:11 = 5 + 5 + 1
例2:

入力:コイン= [2]、量 = 3
出力:-1

1思考:貪欲アルゴリズムは、+ DFS

  1. 迅速Couchuを変更するには、最初に考えたのは、私たち最初の並べ替え、一緒に大きな擦り傷を開始するには、配列、最初の1か最後の1の大きさです。大の小さな場合は、それが大から小に、とき裁判官出口境界を判断することは困難であり、我々は唯一の(境界配列.sizeかどうかを判断する必要がある)ことが、とても小さいに大きな逆イテレータを使用しての最初の注文ができます。
  2. 我々はCouchuこの整数、我々はnum-する必要があり、その後、計算ができない場合は、配列から値を計算していき、量/最大= NUM​​ヶ月の番号を取る、大きなを取得します。
  3. コインの最小数が必要なため、動作を剪定比較した場合、電流はコインのANSの数よりも大きい場合に、電流を節約するためにコインの最小数を定義するようANS、動作中、すなわち、我々は必要ありません
  4. したがって、我々は再帰方程式を導き出すことができます。

DP(コイン、量-NUM *コイン[インデックス]、インデックス+ 1、+ kはカウント、ANS)

コインのアレイがコインである、コインの現在の数がリア一インデックス添字コインで、+ kはコインの現在の数を表すカウント、ANSの数は、電流変化が起こっ表します。
テキストを参照してください。
理解は、コードで直接見て理解することがあれば十分な深学生は、それを理解するには、以下のチャートを見ることができません。
ここに画像を挿入説明
私たちは、単純にすべての再帰的な場合、デクリメントとプルーンバック動作を見つけるために、前進し続けるされています。
コード:

void dp(vector<int>& coins, int amount, int index, int count, int& ans)
{
    if (amount == 0)
    {
        ans = min(ans, count);//找最小值
        return;
    }
    if (index == coins.size()) return;//越界处理
    for (int k = amount / coins[index]; k >= 0 && k + count < ans; k--)//剪枝操作,回溯时k--
    {
        dp(coins, amount - k * coins[index], index + 1, count + k, ans);//递归
    }
}
int coinChange(vector<int>& coins, int amount) 
{
 if(amount == 0)
  return 0;
 sort(coins.rbegin(),coins.rend());//从大到小
 int min = INT_MAX;//用来表示最优解,每次存放最小的。
 dp(coins,amount,0,0,min);
 return min == INT_MAX?-1:min;//等于就表示没有计算。
}

[思考2:]動的プログラミング

  1. これは、問題を解決するための最適なソリューションである、我々は簡単に解決するために、プログラミングのダイナミック考えることができます。最適な基礎構造プロパティ我々は証明するためにここにありません。我々は、トップダウン・アプローチを使用し、最後の時間を加えたコインの最小数のためのコインの次の時間が一定数いることを知っています。
  2. 伝達方程式が導出されます。

F(SC)= F(S)+1。

Cは、コインの現在のサイズを表します。F(S)コインの最小数の合計が場合S.
3. [1,2,3] = 4量をコインを仮定すると、我々は、再帰ツリーを描きます。
ここに画像を挿入説明枝はコインの各選択された値であり、我々はF(S)の値を保持する配列を使用する必要があるので、各時刻が繰り返される値の多数の、計算されることがわかります。
溶液プロセス4.私たちF(3)動的プログラミングの詳細思想に記載されている。
ここに画像を挿入説明
以上の工程により5、我々は、各再帰的にまとめることができる= 0量までダウンし続け、我々は、値を返す、脱積層していきプロセスでは、我々は最小分、一定の比較を保存することでポップ、そして最終的に配列に格納します。コード:私たちはコードを見しようとしていること:

class Solution {
    vector<int>count;//设为全局的,保存最小硬币数
    int dp(vector<int>& coins, int amount) {
        if (amount < 0) return -1;
        if (amount == 0) return 0;
        if (count[amount - 1] != 0) return count[amount - 1];//例如:F(2)=F(1)+F(1)
        int Min = INT_MAX;
        for (int coin:coins) {
            int res = dp(coins, amount - coin);//为当前最少硬币数
            if (res >= 0 && res < Min) {
                Min = res + 1;//加一
            }
        }
        count[amount - 1] = Min == INT_MAX ? -1 : Min;
        return count[amount - 1];
    }
    int coinChange(vector<int>& coins, int amount) {
        if (amount < 1) return 0;
        count.resize(amount);//初始化
        return dp(coins, amount);
    }

私は自分の状況に応じて、第一、第二、考えることはより困難と考えるとああ、私たちは理解し始めました。DFの動的プログラミングと少し難しい、私たちは、ああ燃料を補給する必要があります!

公開された54元の記事 ウォンの賞賛8 ビュー5315

おすすめ

転載: blog.csdn.net/qq_43411555/article/details/105006922