动态规划之求拼成给定数的硬币最小数

本文详细解析了硬币找零问题的算法实现,通过动态规划方法求解使用最少硬币数量完成指定金额找零的方案。文章提供了具体代码示例,展示了如何通过迭代计算得出最优解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:给定一堆固定面值的硬币,比如2,5,7,求拼成指定数值所花费的最小硬币数,比如给定27,最小硬币数应为5,硬币分别为:5,5,5,5,7。这里只用到了一个7,如果自己枚举,可能会先尽可能的用7,那么硬币为:7,7,7,2,2,2,这里就用到了6枚硬币,不是最小数量。

分析:设ak代表最后一枚硬币面值,则ak只可能是2,5,7,本题的最后一步为当 前k-1枚硬币拼法确定的情况下,加上最后一枚硬币ak的面值即可。
设f(x)=最小用多少枚硬币拼出x,
当ak=7时,f(27)=f(27-7)+1
当ak=5时,f(27)=f(27-5)+1
当ak=2时,f(27)=f(27-2)+1
所以f(27)=min{f(27-2)+1,f(27-5)+1,f(27-7)+1}

初始条件为:f[0]=0,因为硬币的面值最小为2,所以f(1)是拼不出来的,这里设置边界情况:f[i]=Integer.MAX_VALUE,当拼不出来的时候就为正无穷。

计算顺序就为从小到大,前面的先计算,后面的可以用前面计算的结果。

代码如下:

package com.coin.test;

public class Main {
	
	public static void main(String[] args){
		int[] A = {2,5,7};
		int M = 27;
		System.out.println(coinMin(A,M));
	}
	
	public static int coinMin(int[] A,int M){
		//A数组存在硬币的种类,M表示能拼成的硬币总和
		//0-M总数为M+1,由于用到数字27,而且数组下标从0开始,所以数组的长度就设置为M+1
		//A数组长度为n,数组下标从0到n-1即可
		int[] f = new int[M+1];
		int n = A.length;
		//设置初始值条件
		f[0]=0;
		
		int i,j;
		for(i=1;i<=M;i++){
			//这里设置边界条件,拼不出来的话就为无穷大
			f[i]=Integer.MAX_VALUE;
			for(j=0;j<n;j++){	
				//这里为边界条件,重要
				//拼成的数值要比硬币的面值要大
				if(i>=A[j] && f[i-A[j]] != Integer.MAX_VALUE){
					//转移方程
					f[i] = Math.min(f[i-A[j]]+1, f[i]);
				}
			}
		}
		
		if(f[M]==Integer.MAX_VALUE){
			f[M] = -1;
		}
		
		return f[M];
		
	}

}

运行结果:

5
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值