动态归划之换零钱

# -*- encoding : utf-8 -*-
# @Author : 日落了
# @ Motto : 天不生python,IT 万古如长夜
# @project_name : DUOyi
# @Time : 2021/12/26
# @description : 凑零钱

# 双函数是为了将num待下去给dp函数 ,因为只是用一个函数的话需要将list写在外面 可读性差,问题来了,dp什么时候需要双参数 什么时候需要一个参数呢?
def func(num, coins: list):
    meno = dict()  # 因为有对应的值,最少的硬币现在的数量的价值

    # 这里的dp含义是dp[n]:当前数值为n的时候 ,所需要最小的硬币数
    def dp(num):
        # 备忘录 n 已经在字典里面的话 ,就不用重复地去计算dp[n]
        if num in meno:
            return meno[num]
        # 通过画出来的递归树可以看到sub问题里面存在着 硬币数为负值或者是0的情况。
        if num == 0:
            return 0
        if num < 0:
            return -1
        # 设置为0的话,min 比较会出错
        res = float('INF')
        for coin in coins:
            # 子问题的含义是 答案 = 前一个子答案加多一个硬币
            sub = dp(num - coin)
            if sub == -1:
                continue

            res = min(sub + 1, res)
        # 字典
        meno[num] = res
        return meno[num]

    return dp(num)


def coinChange(amount: int, coins: list) -> int:
    n = len(coins)
    dp = [[0 for _ in range(n + 1)] for i in range(amount + 1)]
    # 总数为0的时候
    # base
    if amount == 1:
        dp[1][1] = 1
        return 1
    if amount == 0:
        return 0
    for i in range(1, n):
        dp[0][i] = 0

        # dp[1][1] = 1
    for j in range(1, n):
        for i in range(1, amount):
            # 要不起

            if (i < coins[j - 1]):
                dp[i][j] = dp[i][j - 1]
                continue
            dp[i][j] = min(dp[i][j - 1], dp[i - coins[j - 1]][j] + 1)
    return dp[amount][n]


if __name__ == '__main__':
    print(func(11, [1, 2, 5]))
    print(coinChange(11, [1, 2, 5]))
# -*- encoding : utf-8 -*-
# @Author : 日落了
# @ Motto : 天不生python,IT 万古如长夜
# @project_name : DUOyi
# @Time : 2021/12/26
# @description : 凑零钱

# 双函数是为了将num待下去给dp函数 ,因为只是用一个函数的话需要将list写在外面 可读性差,问题来了,dp什么时候需要双参数 什么时候需要一个参数呢?
def func(num, coins: list):
meno = dict() # 因为有对应的值,最少的硬币现在的数量的价值

# 这里的dp含义是dp[n]:当前数值为n的时候 ,所需要最小的硬币数
def dp(num):
# 备忘录 n 已经在字典里面的话 ,就不用重复地去计算dp[n]
if num in meno:
return meno[num]
# 通过画出来的递归树可以看到sub问题里面存在着 硬币数为负值或者是0的情况。
if num == 0:
return 0
if num < 0:
return -1
# 设置为0的话,min 比较会出错
res = float('INF')
for coin in coins:
# 子问题的含义是 答案 = 前一个子答案加多一个硬币
sub = dp(num - coin)
if sub == -1:
continue

res = min(sub + 1, res)
# 字典
meno[num] = res
return meno[num]

return dp(num)


def coinChange(amount: int, coins: list) -> int:
n = len(coins)
dp = [[0 for _ in range(n + 1)] for i in range(amount + 1)]
# 总数为0的时候
# base
if amount == 1:
dp[1][1] = 1
return 1
if amount == 0:
return 0
for i in range(1, n):
dp[0][i] = 0

# dp[1][1] = 1
for j in range(1, n):
for i in range(1, amount):
# 要不起

if (i < coins[j - 1]):
dp[i][j] = dp[i][j - 1]
continue
dp[i][j] = min(dp[i][j - 1], dp[i - coins[j - 1]][j] + 1)
return dp[amount][n]


if __name__ == '__main__':
print(func(11, [1, 2, 5]))
print(coinChange(11, [1, 2, 5]))
原文地址:https://www.cnblogs.com/icxk/p/15747292.html