解题思路
main方法
-
while(true)下,从命令行键入M钱数值,M = 0结束。从命令行键入币种数量K,以及K个数值用数组coins表示
-
调用minCoins(M, coins)方法
-
输出方法返回的值
minCoins(M, coins)方法
-
创建整型数组dp[],用于存储找零金额为
i
时所需的最小硬币数量,初始值设为一个较大的数(2001)。 -
将
dp[0]
设为 0,表示找零金额为 0 时需要的硬币数量为 0。 -
遍历硬币数组
coins
,对于每个硬币面值coin
,再遍历金额i
(从 0 到M
) -
状态方程:dp[i] = Math.min(dp[i], dp[i-coin]+1); 更新
dp[i]
为dp[i]
和dp[i-coin] + 1
中的较小值,表示在使用当前硬币时找零金额为i
需要的最小硬币数量。 -
最终返回
dp[M]
,如果dp[M]
仍然为初始值 2001,则说明无法凑出金额M
,返回字符串 "Impossible";否则返回找零金额M
需要的最小硬币数量。
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (true){
int M = scanner.nextInt();
if(M == 0) break;
int K = scanner.nextInt();
int[] coins = new int[K];
for (int i = 0; i < K; i++) {
coins[i] = scanner.nextInt();
}
System.out.println(minCoins(M,coins));
}
}
private static String minCoins(int M, int[] coins) {
int[] dp = new int[M+1]; //额外的空间来处理边界条件或初始状态。
Arrays.fill(dp,2001);
dp[0] = 0;
for (int coin : coins) {
for (int i = coin; i <= M; i++) {
dp[i] = Math.min(dp[i], dp[i-coin]+1);
}
}
return dp[M] == 2001 ? "Impossible" : String.valueOf(dp[M]);
}
}