题目描述(传送门)
给定数组arr,arr中所有的值都为正整数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个aim,代表要找的钱数,求组成aim的最少货币数。
输入描述:
输入包括两行,第一行两个整数n(0<=n<=1000)代表数组长度和aim(0<=aim<=5000),第二行n个不重复的正整数,代表arr
输出描述:
输出一个整数,表示组成aim的最小货币数,无解时输出-1.
示例
示例1
输入
3 20
5 2 3
输出
4
说明
20=5*4
示例2
输入
3 0
5 2 3
输出
0
示例3
输入
2 2
3 5
输出
-1
思路
状态定义:
dp[i]:表示组成i元,需要找的最少张数
初始化:
dp[0] = 0;
dp[i] = 1000;//i>0取最大值1000
状态方程:
for循环遍历num数组,当i 值大于num的元素就更新dp,负责就不用更新。
具体看代码解释
dp[i] = Math.min(dp[i],dp[i - num[j]] + 1);
返回值:
dp[aim]
代码
import java.util.Arrays;
import java.util.Scanner;
/**
* @ClassName Test1
* @Description 换钱的最小货币数
* @Author fff
* @Date 2020/12/21/11:41
*/
public class Test1 {
/*
3 20
5 2 3
*/
private static int coinChange(int[] num, int amount) {
//动态规划
int[] dp = new int[amount + 1];
dp[0] = 0;
for (int i = 1; i < dp.length; i++) {
dp[i] = 1000;
for (int j = 0; j < num.length; j++) {
if (i >= num[j] && dp[i - num[j]] != 1000) {
// 也可以不对1000做判断,那就得修改后边判断,将==改为 >=
dp[i] = Math.min(dp[i],dp[i - num[j]] + 1);// dp[i - num[j]] + 1其中1就是使用num[j]这张,在加dp[剩余钱数]
}
}
}
return dp[amount] == 1000 ? -1:dp[amount];
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String[] str = scanner.nextLine().split(" ");
int n = Integer.parseInt(str[0]);
int amount = Integer.parseInt(str[1]);
int[] num = new int[n];
//String[] str1 = scanner.nextLine().split(" ");
for (int i = 0; i < n; i++) {
num[i] = scanner.nextInt();
}
System.out.println( coinChange(num , amount));
}
}