【毎日の質問】NiuKe:両替に必要な最低通貨(一次元動的計画法)

タイトルの説明(ポータル

配列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));
    }
}

おすすめ

転載: blog.csdn.net/weixin_45532227/article/details/111474909