题目:给定数组arr,arr中所有的值都为正整数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个aim,代表要找的钱数,求组成aim的最少货币数。
eg:输入:[5,2,3],20 ,输出:4
动归是硬伤啊,还是不会做。
思路应该是对的,针对已有的面值,对前面的每个状态 j 进行计算,但是动归方程到底啥时候用一维啥时候用二维啊....
首先将所有的元素初始化为 Integer.MAX_VALUE-1,然后将 dp[0] 置为0,因为当找零为0时,所需要的数量为0,然后对后面每一数值,首先判断能不能用,即当前面值是否是小于找零钱数的,如果可用的话,使用 min 来决定用不用,不用的话就还是保持现状,用的话,这里只考虑用一张,所以为数量为 dp[i-arr[j]]+1,两者取个最小,(考虑只用一张其实是将问题分解了,比如4的时候,遇到2,用一张,就转换成找2,这个问题已经解决过了)最后在返回的时候判断一下值是不是 Integer.MAX_VALUE-1,是的话return -1,否则return 对应的值。
完整代码如下:
public static int minMoney (int[] arr, int aim) {
// write code here
if(aim==0) {
return 0;
}
if(arr.length==0) {
return -1;
}
int[] dp = new int[aim+1];
Arrays.fill(dp, Integer.MAX_VALUE-1);
dp[0]=0;//需要找0元
for(int i=0;i<aim+1;i++) {
for(int j=0;j<arr.length;j++) {
if(arr[j]<=i) {//可以用 不用的话就保持原来的数据,用的话就进行更新
dp[i] = Math.min(dp[i], dp[i-arr[i]]+1);
}
}
}
return dp[aim]==Integer.MAX_VALUE-1?-1:dp[aim];
}