0-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 -
分析
比如最后一个物品是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背包一维写法
- 分析
因为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背包恰好装满
完全背包
- 分析——转成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])
多重背包
- 分析
转化为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四件物品。
- 例题
# 二进制分解
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))