时间限制:1秒
空间限制:32768K
给你六种面额 1、5、10、20、50、100 元的纸币,假设每种币值的数量都足够多,编写程序求组成N元(N为0~10000的非负整数)的不同组合的个数。
输入描述:
输入包括一个整数n(1 ≤ n ≤ 10000)
输出描述:
输出一个整数,表示不同的组合方案数
输入例子1:
1
输出例子1:
1
分析:
首先想到的是暴力递归方法:
1. 用0张1元货币,让【5、10、20、50、100】组成剩下的N,最终方法数记为res1。
2. 用1张1元货币,让【5、10、20、50、100】组成剩下的N - 1,最终方法数记为res2。
3. 用2张1元货币,让【5、10、20、50、100】组成剩下的N - 2,最终方法数记为res3。
…
N. 用N张1元货币,让【5、10、20、50、100】组成剩下的0,最终方法数记为resN。
import java.util.*;
public class Main{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
int aim = sc.nextInt();
int index = 0;
long sum = count(aim,index);
System.out.println(sum);
}
}
public static long count(int aim, int index){
int[] arr = {1,5,10,20,50,100};
long res = 0;
if(index == arr.length){
res = aim == 0 ? 1 : 0;
} else {
for(int i = 0; arr[index] * i <= aim; i++ ) {
res += count(aim - arr[index] * i, index + 1);
}
}
return res;
}
}
但是这种办法耗时太长,因此需要改进
动态规划方法:
import java.util.*;
public class Main{
public static void main(String[]args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNext()) {
int aim = sc.nextInt();
int[] arr = {1, 5, 10, 20, 50, 100};
System.out.println(count(arr,aim));
}
}
public static long count(int[]arr, int aim) {
long[][] dp = new long[arr.length][aim + 1];
for(int i = 0; i < arr.length; i++) {
dp[i][0] = 1;
}
for(int j = 1; arr[0] * j <= aim; j++) {
dp[0][arr[0] * j] = 1;
}
long num = 0;
for(int i = 1; i < arr.length; i++) {
for(int j = 1; j <= aim; j++) {
num = 0;
for(int k = 0; j - arr[i] * k >= 0; k++) {
num += dp[i - 1][j - arr[i] * k];
}
dp[i][j] = num;
}
}
return dp[arr.length - 1][aim];
}
}