找零钱问题(01背包)

问题描述: Tom在自动售货机上买了一瓶饮料,售价37美分,他投入了1美元(1美元 = 100美分),现在自动售货机需要找钱给他。售货机中现在有6种面额的硬币:1美分,2美分,5美分,11美分,20美分,50美分,每种硬币的数量充足。现在要求使用最少数量的硬币,给Tom找钱,求出这个最少数量是多少 思路:

 

第一步:刻画子结构      

假设Y={y1,y2,y3,y4,y5,y6}是问题的最优解,yi表示找零使用的每种硬币的数量,则y1+y2+y3+y4+y5+y6的值最小。        那么拿出一枚硬币,假设是第i种硬币,其价值为value[i],则剩余的解集合 Y’={y1,…yi-1,…y6}是子问题:使用这6种硬币,为63-value[i] 找零 问题的最优解。

第二步  递归解 记dp[n]表示兑换面值为n的最优解的硬币数       dp[n]= min(dp[n-value[k]]+1)        value[k]<=n 初始条件:   dp[0]=0

import java.util.Scanner;
public class 动态规划_找零钱问题 {
	static int max=63;
	static int[] money=new int[65];
	static int[] m ={0,1,2,5,11,20,50};
	static int dp(int n){
		if(n==1||n==2||n==5||n==11||n==20||n==50) return money[n]=1;
		if(money[n]>0) return money[n];//避免重复计算
		money[n]=max;
		for(int i=1;i<=6;i++){
			if(n>=m[i]) money[n]=Math.min(money[n],dp(n-m[i])+1);
		}
		return money[n];
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc=new Scanner(System.in);
		dp(max);
		System.out.println(money[max]);//50 11 2
	}
}

 

你可能感兴趣的:(01背包,算法设计)