考慮僅用1分、5分、10分、25分和50分這5種硬幣支付某一個給定的金額。例如須要支付11分錢,有一個1分和一個10分、一個1分和一個5分、六個1分和一個5分、十一個1分這4種方式。請寫一個程序,計算一個給定的金額有幾種支付方式。注:假定支付0元有1種方式。java
輸入包含多組數據。每組數據包含一個正整數n(1≤n≤10000),即須要支付的金額。算法
對應每一組數據,輸出一個正整數,表示替換方式的種數。數組
11 26
4 13
假設硬幣的種類數組t={1,5,10,25,50},按大小排序。m表示選擇有0~m種硬幣能夠選擇,面值是t[0]、•••、t[m-1]。要換的錢的數目是n。本題可使用動態規劃算法解決。測試
假設有n錢待找零,當前能夠供選擇的方式爲m種,f(n,m)表示共的待找零方案,則有遞推公式: spa
f(n,m)=⎧⎩⎨10f(n−t[m−1],m)+f(n,m−1)n=0n<0orm≤0n>0andm>0.net
當n=0,f(n,m)=1,表示已經找零完畢,再找0元只有一種方案。
當n<0表示這種方案找零不合理,不能完成找零操做,而m≤0說明找零尚未完成,可是已經沒有能夠供選擇的硬幣了。因此f(n,m)=0。
對於能夠找零,而且還有硬幣選擇的狀況找零有兩種方案。第一種是:選擇一個能夠選擇的最大面值的,剩下的錢再進行找零操做,同時硬幣種類的選擇方案沒有變化,即爲:f(n-t[m-1],m)。第二種是:如今和之後都不選擇本次能夠選擇的最大的硬幣面值,而後再進行找零操做。即f(n,m-1)。code
假設有n錢待找零,當前能夠供選擇的方式爲m種,建立一個長度爲n+1的數組r,r[i]表示找零爲i的找零方法爲r[i]。初始時r的第一個元素爲1,其它元素都爲0,即r[0]=1,r[i≠0]=0。
步驟1、由於硬幣的面值都按大小排序,從最小的面值開始選擇,先選擇最小的一個t[0]。對於找零爲大於0的狀況只有從t[0]開始纔可能有找零的狀況。對於i≥t[0]有r[i]=r[i]+r[i-t[0]]。這是隻有一種硬幣能夠選擇的狀況。
步驟2、當有2種硬幣能夠選擇,在步驟一已經求出了只有一種硬幣可供選擇的狀況,如今能夠選擇第二種硬幣,那麼只有找零數i≥t[0]時才能夠選擇第二種硬幣,因此有r[i]=r[i]+r[i-t[1]]。
同理能夠求得有三、四、•••。具體實現詳見代碼。orm
import java.util.Scanner; /** * Declaration: All Rights Reserved !!! */ public class Main { // 硬幣能夠供選擇的面值 private final static int[] T = {1, 5, 10, 25, 50}; public static void main(String[] args) { Scanner scanner = new Scanner(System.in); // Scanner scanner = new Scanner(Main.class.getClassLoader().getResourceAsStream("data.txt")); while (scanner.hasNext()) { int n = scanner.nextInt(); // System.out.println(exchange(n, T.length)); System.out.println(exchange(n)); } scanner.close(); } /** * 解法一:遞歸解法 * 找零操做 * * @param n 當前要找的零錢數 * @param m 能夠選擇的硬幣種類T[0]~T[m-1] * @return 不的找零數目 */ private static int exchange(int n, int m) { if (n == 0) { return 1; } else if (n < 0 || m <= 0) { return 0; } else { return exchange(n - T[m - 1], m) + exchange(n, m - 1); } } /** * 解法二:非遞歸解法 * 找零操做 * * @param n 當前要找的零錢數 * @return 不的找零數目 */ private static long exchange(int n) { // 選擇long否則可能會超出int表達範圍 long[] result = new long[n + 1]; // 初始化 result[0] = 1; // 每次增長一種硬幣,且比以前硬幣的面值大,計算加入新的硬幣後每一個數目的錢其找零數有多少種 for (int t : T) { for (int j = t; j <= n; j++) { result[j] += result[j - t]; } } return result[n]; } }