
class Solution(object):
def change(self, amount, coins):
"""
:type amount: int
:type coins: List[int]
:rtype: int
"""
# 完全背包
# 每一种面额的硬币有无限个
# dp[j]:金额为j的组合数,最终目标是dp[amount]
# 此时的金额j-当前手上的硬币coins[i]=还差多少钱(j-coins[i])
# 状态转移方程:dp[j]=dp[j-coin]+dp[j]
# dp[j-coin]是选取当前coin的组合数,因为你要选取coin的话,那就说明当前还差coin
# dp[j]说明不选当前的coin,不用当前硬币,达到金额j的组合数,dp[j]一定在前面一个循环就算出来了,因为第一个遍历就是遍历手中的硬币
# 初始化:dp[0]=1,金额为0,只有一种组合方式就是什么都不选
dp = [0]*(amount+1)
dp[0] = 1
for coin in coins:
# 这里是可以从小到大遍历的,这是完全背包与01背包的区别
# 01背包是倒序,大-小。完全背包是正序,小-大
# 01背包倒序的原因就是避免重复,每个元素用一次
# 完全背包就是元素为无限个,这个区别要记住
# 这里还可以优化,不用0开始遍历,也就不需要下面的判断了
# for i in range(amount+1):
# if coin>i:
# continue
# elif coin<=i:
# dp[i] += dp[i-coin]
# return dp[-1]
# 优化,此时i一定是>=coin
for i in range(coin, amount+1):
dp[i] += dp[i-coin]
return dp[-1]