背包问题(动态规划)

0-1背包

  1. 普通0-1背包在这里插入图片描述
    贪心不合适
    不能优先放价值大的,比如:
    9 10, 5 6, 5,5 很明显6+5>10
    也不能优先放性价比高的,比如:
    9 18, 5, 9.5, 5,9.5 最大的性价比是2,但是放进去价值18<9.5+9.5=19

  2. 分析
    比如最后一个物品是4 6,也就是重量是4,价值是6,那么最优解一定来自:前四个物品在容量为6的情况下最大值加上第五个物品的价值6,或者前四个物品在容量为10的情况下的价值,也就是 不要第五个物品,显然两者取个最大值。

在这里插入图片描述
3. 例题
在这里插入图片描述

T, M = [int(x) for x in input().split()]
# T 是采样时间,相当于背包容量
# M 是多少行数据
value = [0]
time = [0]
for _ in range(M):
    line = [int(x) for x in input().split()]
    time.append(line[0])
    value.append(line[1])

dp = [[0] * (T+1) for _ in range(M+1)]
# 初始化左边一列和上边一行为0,也就是背包容量为0时价值为0,
# 背包物品数目为0时,价值为0

for i in range(1, M+1):
    for j in range(1, T+1):
        if j >= time[i]:
            dp[i][j] = max(dp[i-1][j],dp[i-1][j-time[i]] + value[i])
        else:
            dp[i][j] = dp[i-1][j] # 这里一定要加上,否则就是0

print(dp[M][T])

0-1背包一维写法

  1. 分析

因为dp[i][j]只跟二维表格的前面两个数字有关系,只跟上一行有关系,说以浪费了很多空间,一定要倒着写
在这里插入图片描述

dp = [0] * (T+1)
for i in range(1, M+1):
    for j in range(T, time[i]-1, -1):
        dp[j] = max(dp[j],dp[j-time[i]]+value[i])
            
print(dp[T])

0-1背包恰好装满

在这里插入图片描述
在这里插入图片描述

完全背包

在这里插入图片描述

  1. 分析——转成0-1背包

在这里插入图片描述
2. 选第i个物品,选多少个
3.在这里插入图片描述
在这里插入图片描述
3. 例题
在这里插入图片描述
在这里插入图片描述
超时了

T, M = sys.stdin.split()
# T, M = [int(x) for x in input().split()]
# T 是采样时间,相当于背包容量
# M 是多少行数据
value = [0]
time = [0]
for _ in range(M):
    line = [int(x) for x in input().split()]
    time.append(line[0])
    value.append(line[1])

dp = [0] * (T+1)

for i in range(M+1):
    for j in range(time[i],T+1):
        dp[j] = max(dp[j],dp[j-time[i]]+value[i])
        
print(dp[T])

在这里插入图片描述

多重背包

  1. 分析

转化为0-1背包问题。把第i种物品换成n[i]件0-1背包中的物品,将第i中物品分成若干件物品,其中每件物品都有一个系数,这件物品的费用和价值均是原来的费用和价值乘以这个系数。使这些系数分别为1,2,4,…2(k-1),n[i]-2k+1,且是满足n[i]-2^k+1< 2 ^(k+1),例如13,就是1, 2,4, 6四件物品。

  1. 例题
    在这里插入图片描述
    在这里插入图片描述


# 二进制分解
def binaryDecomposition(n):
    k = 0
    res = []
    while n > 2**k:
        res.append(2**k)
        n = n - 2 **k
        k = k + 1
    res.append(n)
    return res


def trans(weight, value, nums):
    new_weight = []
    new_value = []
    for i in range(len(nums)):
        for j in binaryDecomposition(nums[i]):
            new_weight.append(j * weight[i])
            new_value.append(j * value[i])
    n = len(new_value)
    return n, new_weight, new_value



while True:
    M, T = [int(x) for x in input().split()]
    if M == 0 and T == 0:
        break
    line = [int(x) for x in input().split()]
    time = line[:M]
    value = line[:M]
    nums = line[M:]

    new_M, new_time, new_value = trans(time, value, nums)

    res = set()
    dp = [0] * (T+1)
    for i in range(1, new_M+1):
        for j in range(T, new_time[i-1]-1, -1):
            dp[j] = max(dp[j], dp[j-new_time[i-1]] + new_value[i-1])
            res.add(dp[j])

    print(len(res))

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值