有数量不限的硬币,币值为25分、10分、5分和1分,请编写代码计算n分有几种表示法。
给定一个int n,请返回n分有几种表示法。
import java.util.Arrays;
/*
* 我们用数组coins[i]={1,5,10,25}表示各种币值,此时可以维护一张二维表ways[i][j],
* 其中横坐标表示前i种表示币值,j表示硬币的总值,
* 则ways[i][j]表示能用前i种硬币来表示j分的方法数。
当增加一种新的硬币币值时,有两种情况:
(1)不加入此种币值:ways[i][j]=ways[i-1][j];
(2)加入此种币值:加入该枚硬币之前的方法数为ways[i-1][j],那么加入该枚硬币之后构成j分的方法数也为ways[i][j-coins[i]]。
因此当增加一种新的币值时,j分的表示方法数为ways[i][j]=ways[i-1][j]+ways[i][j-coins[i]]。
*/
public class Demo1 {
public static void test2(int n){
//纸币面额
int money[]={0,1,5,10,20,50,100};
int dp[][] = new int[6+1][n+1];
for (int i = 0; i < dp.length; i++) {
dp[i][0] = 1 ;
}
for (int i = 0; i < dp[0].length; i++) {
dp[0][i] = 0;
}
for(int i = 1;i < dp.length ;++i){
for(int j = 1;j < dp[0].length;++j){
if (j >= money[i])
dp[i][j] = dp[i - 1][j] + dp[i][j - money[i]];
else
dp[i][j] = dp[i - 1][j];
}
}
for (int i = 0; i < dp.length; i++) {
System.out.println(Arrays.toString(dp[i]));
}
System.out.println(dp[6][n]+"============");
}
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
//指定200元的金额
test2(11);
long endTime = System.currentTimeMillis();
System.out.println("执行时间:" + (endTime - startTime) + "ms");
}
}
本代码是下面的题的答案
import java.util.Scanner;
public class Main1 {
private static int process(int[] counts, int x) {
int sum = 0;
int count = 0;
//硬币面额
int[] a = {1, 5, 10, 20, 50, 100};
for (int i = 0; i <= x / a[5] && i <= counts[5]; i++) {
//100元可能出现的张数
for (int j = 0; j <= x / a[4]&& j <= counts[4]; j++) {
//50元可能出现的张数
for (int k = 0; k <= x / a[3]&& k<= counts[3]; k++) {
//20元可能出现的张数
for (int l = 0; l <= x / a[2]&& l <= counts[2]; l++) {
//10元可能出现的张数
for (int m = 0; m <= x / a[1]&& m <= counts[1]; m++) {
//5元可能出现的张数
//for(int n=0;n<x/1;n++){//这步循环可省略
int n = x - (i * a[5] + j * a[4] + k * a[3] + l * a[2] + m * a[1]);
sum = i * a[5] + j * a[4] + k * a[3] + l * a[2] + m * a[1] + n * a[0];
if (sum == x && n >= 0 && n <= counts[0]) {
System.out.println(n+" "+m+" "+l+" "+k+" "+j+" "+i);
count += n+m+l+k+j+i;
}
}
}
}
}
}
return count;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int[] counts = new int[6];
for (int i = 0; i < counts.length; i++) {
counts[i] = sc.nextInt();
}
int total = sc.nextInt();
int sum = process(counts, total);
System.out.println(sum);
}
}
输入和输出
6 5 4 3 2 1
11
6 1 0 0 0 0
1 2 0 0 0 0
1 0 1 0 0 0
12
加上时间和循环次数的判断
import java.util.Scanner;
public class Main1 {
public static int process(int[] counts, int x){
int result = 0;
int sum = 0;
//符合条件的组合次数
int count = 0;
//循环次数
int times = 0;
//硬币面额
int[] a = {1, 5, 10, 20, 50, 100};
for (int i = 0; i <= x / a[5] && i <= counts[5]; i++) {
//100元可能出现的张数
for (int j = 0; j <= x / a[4]&& j <= counts[4]; j++) {
//50元可能出现的张数
for (int k = 0; k <= x / a[3]&& k<= counts[3]; k++) {
//20元可能出现的张数
for (int l = 0; l <= x / a[2]&& l <= counts[2]; l++) {
//10元可能出现的张数
for (int m = 0; m <= x / a[1]&& m <= counts[1]; m++) {
//5元可能出现的张数
//for(int n=0;n<x/1;n++){//这步循环可省略
int n = x - (i * a[5] + j * a[4] + k * a[3] + l * a[2] + m * a[1]);
sum = i * a[5] + j * a[4] + k * a[3] + l * a[2] + m * a[1] + n * a[0];
times++;
if (sum == x && n >= 0 && n <= counts[0]) {
count++;
System.out.println(n+" "+m+" "+l+" "+k+" "+j+" "+i);
result += n+m+l+k+j+i;
}
}
}
}
}
}
System.out.println("循环次数:" + times);
System.out.println("组合数:" + count);
return result;
}
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
Scanner sc = new Scanner(System.in);
int[] counts = new int[6];
for (int i = 0; i < counts.length; i++) {
counts[i] = sc.nextInt();
}
int total = sc.nextInt();
int sum = process(counts, total);
System.out.println(sum);
long endTime = System.currentTimeMillis();
System.out.println("执行时间:" + (endTime - startTime) + "ms");
}
}
6 5 4 3 2 1
11
6 1 0 0 0 0
1 2 0 0 0 0
1 0 1 0 0 0
循环次数:6
组合数:3
12
执行时间:3381ms