解題想法

題目要問的是給定一個金額,請問用{1, 5, 10, 25, 50}來湊的話,共有幾種不同的湊法。

這題其實就是無限背包問題,所以會用到動態規劃的概念。只是把背包的限制重量變成題目欲湊出的金額。物品變成面額。 然後面額的數量沒有限制,隨你喜歡用多少就用多少。

可以分別考慮加上每個面額後,能湊出該金額的方法數會如何變化。 也就是以下的這個轉移式:

dp(金額) += dp(金額 - 當下面額)

如果先考慮一個固定金額,再考慮每加上不同面額,方法數會有甚麼改變(就是把for迴圈內外顛倒)。這樣會造成在考慮方法數的時候會重複計算。

十元來舉例

首先加上 $9 的方法數($1 * 9, $5 + $1 * 4)

再加上 $5 的方法數($1 * 5, $5)

會發現 $9 的第二個方法跟 $5 的第一個方法,在分別加上 $1 以及 $5 後會變成相同的方法,這樣就重複計算到了。

程式碼

#include <iostream>
using namespace std;

int main()
{
    int dp[8000] = {1};
    int coins[5] = {1, 5, 10, 25, 50};

    for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 8000; j++) {
            if (j - coins[i] >= 0)
                dp[j] += dp[j - coins[i]];
        }
    }

    int money;
    while (cin >> money) 
        cout << dp[money] << endl;

    return 0;
}