zoukankan      html  css  js  c++  java
  • 518.零钱兑换 II

    给定不同面额的硬币和一个总金额。写出函数来计算可以凑成总金额的硬币组合数。假设每一种面额的硬币有无限个。 

    示例 1:

    输入: amount = 5, coins = [1, 2, 5]
    输出: 4
    解释: 有四种方式可以凑成总金额:
    5=5
    5=2+2+1
    5=2+1+1+1
    5=1+1+1+1+1
    示例 2:

    输入: amount = 3, coins = [2]
    输出: 0
    解释: 只用面额2的硬币不能凑成总金额3。
    示例 3:

    输入: amount = 10, coins = [10]
    输出: 1
     

    注意:

    你可以假设:

    0 <= amount (总金额) <= 5000
    1 <= coin (硬币面额) <= 5000
    硬币种类不超过 500 种
    结果符合 32 位符号整数

    思路:

      • [0-1]背包 问题:当前考虑的物品拿或者不拿;
      • [完全]背包 问题:当前考虑的物品拿或者不拿,如果拿,只要背包能装下,就可以一直拿,直到背包装不下为止。
      • 此题:动态规划(完全背包问题),求组合数,设 dp[i][j] 表示使用前 i种硬币组成金额 j 的组合数;
      • dp[i][j] = dp[i-1][j] + dp[i][ j-coins[i] ] ,即,对于当前的硬币 coins[i] 来说,组成金额 j 有两种情况,如果不使用这个硬币 i,而是使用前 i-1个硬币组成金额 j 的组合数为 : dp[i-1][j] ,如果使用这个硬币 i,则组合数等于 : dp[i][j - coins[i] ];

              

                             注:图片来源 Liucx

      • 一个一个物品考虑,容量一点一点扩大,整个过程就是尝试和比较的过程。

      •  代码(二维矩阵):

    class Solution {
        public int change(int amount, int[] coins) {
            int n = coins.length;
            int[][] dp = new int[n + 1][amount + 1];
            dp[0][0] = 1; //当 amount = 0 时,有 1 种方案
            for(int i = 1; i <= n; i++){ // 第 i 个硬币,从下标 1 开始
                int coin = coins[i-1]; //硬币金额
                for(int j = 0; j <= amount; j++){ //背包容量从 0 慢慢扩大到 amount
                    if(j < coin) dp[i][j] = dp[i-1][j]; //当背包容量小于当前硬币金额,此硬币不用考虑
                    else dp[i][j] = dp[i-1][j] + dp[i][j-coin]; //否则,一直放当前硬币
                    }
            }
            return dp[n][amount]; // n 个硬币都放完,背包容量为 amount 的组合数
            }
    }

      •  优化,利用滚动数组进行空间压缩;

      •  代码(一维数组):

    class Solution {
        public int change(int amount, int[] coins) {
            int[] dp = new int[amount + 1];
            dp[0] = 1; //当 amount = 0 时,有 1 种方案
            for(int i = 0; i < coins.length; i++){
                int coin = coins[i]; //硬币金额
                for(int j = coin; j <= amount; j++){ //背包容量从当前硬币 coin 慢慢扩大到 amount
                    dp[j] = dp[j] + dp[j-coin];
                }
            }
            return dp[amount];
        }
    }
  • 相关阅读:
    uva 10369 Arctic Network
    uvalive 5834 Genghis Khan The Conqueror
    uvalive 4848 Tour Belt
    uvalive 4960 Sensor Network
    codeforces 798c Mike And Gcd Problem
    codeforces 796c Bank Hacking
    codeforces 768c Jon Snow And His Favourite Number
    hdu 1114 Piggy-Bank
    poj 1276 Cash Machine
    bzoj 2423 最长公共子序列
  • 原文地址:https://www.cnblogs.com/luo-c/p/13949745.html
Copyright © 2011-2022 走看看