タイトルの説明(ポータル)
配列arrが与えられると、arrのすべての値は正の整数であり、繰り返されません。各値は金種の通貨を表し、各金種の任意の通貨を使用できます。見つけられる金額を表す目的が与えられた場合、目的を構成する通貨の最小数を見つけます。
説明を入力してください:
输入包括两行,第一行两个整数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));
}
}