假设有3种不同的硬币,币值分别是CoinValue[] = {1, 2, 5},每一种硬币的数量是有限的,分别是CoinNum[] = {3, 3, 3},给定一个数值target=18,找出一种硬币数最少的方法, 输出最少的硬币数。
思路:我们考虑用动态规划解决这个问题,动态规划的基本宗旨是:无后效性,他只能利用先前的知识来推导出后面的知识。最重要的是要有状态转移方 程。我们可以把大问题化为小问题,从局部问题求解。
假如:我们选取dp(i)表示存够i元最少需要的硬币数。
dp(0) = 0: 表示存够0元最少需要0枚硬币
dp(1)=1:首先找到小于等于1的硬币,发现只有1,选取此枚硬币,只需找到凑够0元需要的最少硬币数,即dp(1) = dp(1-1)+1=1(此处加1表示因为所求的是硬币的数量,开始处已经选取了1枚硬币,所以需要把这个1加上。)
dp(2)=2:首先找到小于等于2的硬币,发现有1、2,先选取1这枚硬币,只需找到凑够1元需要的最少硬币数,即dp(2)=dp(2-1)+1=dp(1)+1=2,也可以是选取2这枚硬币,只需找到凑够0元需要的最少硬币数,即dp(2)=dp(2-2)+1=dp(0)+1=1,由于,我们需要找的是凑够2元的最少硬币数,所以,我们需要在2和1之间取一个最小值,即Math.min{dp(2-1)+1,dp(2-2)+1}。
以下情况类似。
从以上可以发现:状态转移方程:dp(i) = Math.min{dp(i-coinValue(j))+1},coinValue()表示存储的硬币种类。
需要注意的是:假设我们需要i元的最少硬币数,我们需要构建一个i+1的数组,存储dp(0) = 0,因为dp(i)从1存储,有dp(i-1)。
import java.util.*;
public class MinCoin {
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
while(scan.hasNext()){
int totalPrice = scan.nextInt();
int number = scan.nextInt();
int[] value = new int[number];
for(int i=0;i<number;i++){
value[i] = scan.nextInt();
}
int[] type = new int[totalPrice+1];
type[0] = 0;
int minType = 0;
for(int i=1;i<totalPrice+1;i++){
minType = i;
for(int j=0;j<value.length;j++){
if((value[j]<=i)&&(type[i-value[j]]+1)<minType){
minType = type[i-value[j]]+1;
}
}
type[i] = minType;
}
System.out.println(type[totalPrice]);
}
}
}