此筆記為UVa 00674的題目詳解,包含解題思路、C++範例程式碼。
Coin Change (ZeroJudge d253.)
題目
給你一個金額( n cents),請你回答共有多少種硬幣組合的方式。例如:n=11,那麼你可以有以下4種硬幣的組合:
1. 1個 10 cent的硬幣加上1個 1 cent的硬幣
2. 2個 5 cent的硬幣加上1個 1 cent的硬幣
3. 1個 5 cent的硬幣加上6個 1 cent的硬幣
4. 11個 1 cent的硬幣
p.s 美國的零錢共有以下5種硬幣以及其面值:
• penny, 1 cent
• nickel, 5 cents
• dime, 10 cents
• quarter, 25 cents
• half-dollar, 50 cents
請注意:n=0 我們算他是有一種方式。
輸入 / 輸出說明
| 輸入說明 | 輸出說明 |
|---|---|
| 每組測試資料1列,有1個整數n(0 <= n <= 7489),代表零錢的總金額(單位:cent)。 | 對每組測試資料請輸出共有多少種硬幣組合方式。 |
解題思路
教大家一個辨別要用貪心法還是動態規劃的方法:
當你遇到求最小問題的時候:
1. 面額全部具備倍數關係:貪心法
2. 面額不具備倍數關係:動態規劃
當你遇到求方法數的時候,要用動態規劃去做。
好現在回來這一題,這一題我們可以只用一維的陣列做動態規劃,但前提是小的要先做。
這邊要注意付 0 我們是 1 種方法 (什麼都不付)。
一開始因為 1 塊錢在付任何金額的情況下都只有一種方法,先初始化付 i 塊錢的方法數 dp[i] = 1, $1 \le i \le 10000$。
接著我們可以看新增不同面額 dollar[i] 後,方法數 dp[j] 的變化就是 dp[j] += dp[j-dollar[i]]。
舉例而言:
當我們要付 10 塊 (dp[10]) 的時候,用 1 塊錢付的方法就是 1 種,目前 dp[10] 是 1。
現在看新增 5 塊面額的時候,付 10 塊的方法就會變成 dp[10] + dp[10-5],因為這題目可以拆成:
1. 原本的 dp[10] 是用 1 塊錢的方法
2. dp[5] = dp[10-5] 是先用了一個 5 塊錢之後,剩下 5 塊錢怎麼用的方法。
因為我們會從小到大維護這個陣列,所以 dp[5] 已經被維護過,他是 dp[5] + dp[0] = 2 種方法:
1. 原本的 dp[5] 是用 1 塊錢的方法
2. dp[0] = dp[5-0] 是先用了一個 5 塊錢之後,剩下 0 塊錢怎麼用的方法,顯然是 1 種。
所以 dp[5] 已經是 2,現在的 dp[10] = dp[10] + dp[10-5] = 1 + 2 = 3。
範例程式碼
1 |
|
運行結果
AC (4ms, 368KB)
查看更多資訊請至:https://www.tseng-school.com/