【每日一题】牛客:换钱的最少货币数(一维动态规划)

题目描述(传送门)

给定数组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));
    }
}

你可能感兴趣的:(每日一题,动态规划,leetcode,算法)