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
解题思路
完全背包问题
状态数组和basecase很好理解。注释有表标
递进关系:
如果容量不支持使用该硬币,则直接不适用,等于用前i-1个元素装
如果容量支持,则可装可不装。组合数相加。不装同上
装上时,我们可以只求装一次,那么组合数就为用前i个去装总容量-当前容量的子问题。
之所以是前i个,而不是前i-1个,就是因为第i个物品可以多次装载
图片说明

class Solution {
    public int change(int amount, int[] coins) {
        int n=coins.length;
        //dp[i][j]表示用前i个面值的硬币可以凑出j总数的组合数
        int[][] dp=new int[n+1][amount+1];
        //base case:dp[0][...]:0--没有硬币,凑不出来---dp[...][0]=1---总数为0,不用凑为一种组合
        for(int i=0;i<=n;i++){
            dp[i][0]=1;
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=amount;j++){
                if(j-coins[i-1] < 0){
                    //不放此硬币:
                    dp[i][j]=dp[i-1][j];
                }
                else{
                    //放此硬币,则直接放一次(可以多次,多次可以依赖子问题实现)
                    //可放可不放
                    dp[i][j]=dp[i][j-coins[i-1]]+dp[i-1][j];
                }
            }
        }
        return dp[n][amount];
    }
}