KY14 最小邮票数

KY14 最小邮票数

动态规划法

# KY14 最小邮票数 
# 邮票需要凑的总面值为M,可选邮票的总数是N
# 邮票i的面值保存为values[i]
# 动态规划法求解,dynamic programming
# 令 dp[i][j]表示只允许总前i张邮票中
# 选择,并且凑到总面值j,所需最小邮票数量
# 边界条件,若: i*j == 0, 则dp[i][j] = 0
# 求解dp[i][j]:
# 若:j<values[i],则dp[i][j] = dp[i-1][j]
# 若:j==values[i],则dp[i][j] = 1
# 若:j>values[i],
#   若:dp[i-1][j-values[i]] > 0,
#       若dp[i-1][j]>0:
#           则dp[i][j] = min([1+dp[i-1][j-values[i]],dp[i-1][j]])
#       否则:dp[i][j] = 1 + dp[i-1][j-values[i]]
#   若:dp[i-1][j-values[i]] < 0,则dp[i][j] = dp[i-1][j]

def print_min_amount(TotalValue, StampAmount):
    values = (0,) + tuple(map(eval, input().strip().split()))
    dp = [[0 for j in range(1+TotalValue)] for i in range(1+StampAmount)]
    for i in range(1, 1+StampAmount):
        for j in range(1, 1+TotalValue):
            if j < values[i]:
                dp[i][j] = dp[i-1][j]
            elif j == values[i]:
                dp[i][j] = 1
            else:  # j > values[i]
                if dp[i-1][j-values[i]] > 0:
                    if dp[i-1][j]>0:
                        dp[i][j] = min([
                            1 + dp[i-1][j-values[i]],
                            dp[i-1][j]
                        ])
                    else:
                        dp[i][j] = 1 + dp[i-1][j-values[i]]

                else:
                    dp[i][j] = dp[i-1][j]
    print(dp[StampAmount][TotalValue])

if __name__ == '__main__':
    try:
        while True:
            TotalValue = eval(input().strip())
            StampAmount = eval(input().strip())
            print_min_amount(TotalValue, StampAmount)
    except EOFError:
        pass

空间优化版:

# KY14 最小邮票数 
# 邮票需要凑的总面值为M,可选邮票的总数是N
# 邮票i的面值保存为values[i]
# 动态规划法求解,dynamic programming
# 令 dp[i][j]表示只允许总前i张邮票中
# 选择,并且凑到总面值j,所需最小邮票数量
# 边界条件,若: i*j == 0, 则dp[i][j] = 0
# 求解dp[i][j]:
# 若:j<values[i],则dp[i][j] = dp[i-1][j]
# 若:j==values[i],则dp[i][j] = 1
# 若:j>values[i],
#   若:dp[i-1][j-values[i]] > 0,
#       若dp[i-1][j]>0:
#           则dp[i][j] = min([1+dp[i-1][j-values[i]],dp[i-1][j]])
#       否则:dp[i][j] = 1 + dp[i-1][j-values[i]]
#   若:dp[i-1][j-values[i]] < 0,则dp[i][j] = dp[i-1][j]


# 法二,空间优化版
# 改进版: 减少空间占用
def print_min_amount(TotalValue, StampAmount):
    stampsValues = (0,) + tuple(map(eval, input().strip().split()))
    dp = [0 for j in range(1 + TotalValue)]
    for stampIndex in range(1, StampAmount + 1):
        for value in range(TotalValue, 0, -1):
            if stampsValues[stampIndex] == value:
                dp[value] = 1
            elif stampsValues[stampIndex] > value:
                pass  # dp[value] = dp[value]
            else:  # stampsValues[stampIndex] < value
                if dp[value-stampsValues[stampIndex]] > 0:
                    if dp[value] > 0:
                        dp[value] = min([
                            1 + dp[value-stampsValues[stampIndex]],
                            dp[value]
                        ])
                    else:
                        dp[value] = 1 + dp[value-stampsValues[stampIndex]]
                else:
                    pass  # dp[value] = dp[value]
    print(dp[TotalValue])

if __name__ == '__main__':
    try:
        while True:
            TotalValue = eval(input().strip())
            StampAmount = eval(input().strip())
            print_min_amount(TotalValue, StampAmount)
    except EOFError:
        pass
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值