Java 硬币凑数问题

问题描述:硬币分别有面值分别为1,5, 10, 25四种面值。输入一个整数n,用这些硬币组合成数值n,问有多少种组合方式?

解法一:暴力破解,用四个for循环破解。

代码如下:


import java.util.Scanner;

public class 硬币凑数问题 {
	public static void main(String[] args){
		Scanner scanner = new Scanner(System.in);
		int n = scanner.nextInt();
		System.out.println(solve(n));
	}
	/**
	 * for循环暴力法破解
	 * @param n
	 * @return
	 */
	private static int solve(int n) {
		int sum = 0;
		for(int i=0; i<=n; i++){
			for(int j=0; j*5<=n; j++){
				for(int k=0; k*10<=n; k++){
					for(int l=0; l*25<=n; l++){
						if((i+5*j+k*10+l*25 == n)) sum++;
					}
				}
			}
		}
		return sum;
	}
}

解法二:用递推的方法实现,这个递归关键在于变量的设置,设三个变量,第一个是需要凑的数值n;第二个是一个数组表arr示硬币的面值,是固定不变的;第三个是硬币的可用范围m,也就是数组下标。当前可用的最大硬币面值是arr[m]。
分解过程是这样的将凑整数n分解为:用一个arr[m]参与组合,用2arr[m]参与组合,用3arr[m]参与组合,一直分解到iarr[m], 当ia>n时停止。
边界出口就是当m0时,也就是只能用面值为1的硬币进行组合的时候,这时只有一种组合(剩余的数值都用面值为1的硬币来凑)。当n0时,返回1,而不是返回0;返回0的话最终结果会比正确答案少1。因为n==0表示的情况是剩余的数值是0,也就是说上一次数值刚好是最大面值的整数倍。举个列子:假设数值是100,则刚好可以用4个25面值的硬币表示剩余值为0;这也一种组合方式。所以应该返回的值1。
这题需要注意的地方是它是多分支的分解情况,与寻常递归只有两三种分支情况不同(比如斐波那契数列求和)。所以这题需要再循环中进行递归。
递归最需要注意的地方就是分解的表达式和出口是否正确。

代码如下:


import java.util.Scanner;

public class 硬币凑数问题 {
	public static void main(String[] args){
		Scanner scanner = new Scanner(System.in);
		int n = scanner.nextInt();
		int[] a = {1,5,10,25};
		System.out.println(solve(n, a, 3));
	}
	
	private static int solve(int n, int[] a, int m) {
		int res = 0;
		if(m==0) return 1;
		if(n==0) return 1;
		for(int i=0; i*a[m]<=n; i++){
			res = res + solve(n-i*a[m], a, m-1);
		}
		return res;
	}
}
发布了45 篇原创文章 · 获赞 5 · 访问量 1940

猜你喜欢

转载自blog.csdn.net/HC199854/article/details/104291026