动态规划/递归 | HJ16 购物单
# 最优解1:动态规划
n, m = map(int,input().split())
primary, annex = {}, {}
for i in range(1,m+1):
x, y, z = map(int, input().split())
if z==0:#主件
primary[i] = [x, y]
else:#附件
if z in annex:#第二个附件
annex[z].append([x, y])
else:#第一个附件
annex[z] = [[x,y]]
m = len(primary)#主件个数转化为物品个数
dp = [[0]*(n+1) for _ in range(m+1)]
w, v= [[]], [[]]
for key in primary:
w_temp, v_temp = [], []
w_temp.append(primary[key][0])#1、主件
v_temp.append(primary[key][0]*primary[key][1])
if key in annex:#存在主件
w_temp.append(w_temp[0]+annex[key][0][0])#2、主件+附件1
v_temp.append(v_temp[0]+annex[key][0][0]*annex[key][0][1])
if len(annex[key])>1:#存在两主件
w_temp.append(w_temp[0]+annex[key][1][0])#3、主件+附件2
v_temp.append(v_temp[0]+annex[key][1][0]*annex[key][1][1])
w_temp.append(w_temp[0]+annex[key][0][0]+annex[key][1][0])#3、主件+附件1+附件2
v_temp.append(v_temp[0]+annex[key][0][0]*annex[key][0][1]+annex[key][1][0]*annex[key][1][1])
w.append(w_temp)
v.append(v_temp)
for i in range(1,m+1):
for j in range(10,n+1,10):#物品的价格是10的整数倍
max_i = dp[i-1][j]
for k in range(len(w[i])):
if j-w[i][k]>=0:
max_i = max(max_i, dp[i-1][j-w[i][k]]+v[i][k])
dp[i][j] = max_i
print(dp[m][n])
# 最优解2:递归
def solve(i, j):
"""
i表示遍历到第i件物品,j表示剩余钱数
"""
if i == n+1:
return 0
if dp[i][j] != 0:
return dp[i][j]
if v[i - 1] > j or a[i - 1] != 0:
dp[i][j] = solve(i + 1, j)
if j >= v[i - 1] and a[i - 1] == 0: # 买得起索引为i-1的物品
lst = []
for inx in range(n):
if a[inx] == i:
lst.append(inx)
if len(lst) == 0: # 没有附件
dp[i][j] = max(solve(i+1, j), solve(i+1, j-v[i - 1])+s[i-1])
elif len(lst) == 1: # 有1个附件
dp[i][j] = max(solve(i+1, j), solve(i+1, j-v[i - 1])+s[i-1])
if v[i-1]+v[lst[0]] <= j:
dp[i][j] = max(dp[i][j], solve(i+1,j-v[i-1]-v[lst[0]])+s[i-1]+s[lst[0]])
elif len(lst) == 2: # 有2个附件
dp[i][j] = max(solve(i+1, j), solve(i+1, j-v[i - 1])+s[i-1])
i1, i2 = lst
if v[i-1]+v[i1] <= j: # 可以买主件+附件1
dp[i][j] = max(solve(i+1, j), solve(i+1, j-v[i - 1])+s[i-1],
solve(i+1, j-v[i-1]-v[i1])+s[i-1]+s[i1])
if v[i-1]+v[i2] <= j: # 可以买主件+附件2
dp[i][j] = max(solve(i+1, j), solve(i+1, j-v[i - 1])+s[i-1],
solve(i+1, j-v[i-1]-v[i2])+s[i-1]+s[i2])
if v[i-1]+v[i1]+v[i2] <= j: # 可以买主件+附件1+附件2
dp[i][j] = max(solve(i+1, j), solve(i+1, j-v[i - 1])+s[i-1],
solve(i+1, j-v[i-1]-v[i1])+s[i-1]+s[i1],
solve(i+1, j-v[i-1]-v[i2])+s[i-1]+s[i2],
solve(i+1, j-v[i-1]-v[i1]-v[i2])+s[i-1]+s[i1]+s[i2])
return dp[i][j]
while True:
try:
m, n = list(map(int, input().split(" ")))
v, s, a = [], [], []
m //= 10
for i in range(n):
value, pri, attach = list(map(int, input().split()))
v.append(value // 10)
s.append(pri*value)
a.append(attach)
dp = [[0] * (m + 1) for _ in range(n + 1)]
res = solve(1, m)
print(res)
except:
break
# 我的代码:参考动态规划最优解
class Good:
def __init__(self, id, price, weight, belong) -> None:
self.id = id # 商品编号
self.price = price # 商品价格
self.weight = weight # 商品满意度:价格*重要度
self.belong = belong
self.attach = [] # 商品附件
def add_attach(self, good):
self.attach.append(good)
while True:
try:
m, N = list(map(int, input().split(" ")))
# 1、dp数组长度为总钱数,将商品价格与总钱数同比缩小10倍,缩小dp长度
# 2、dp由2维减为1维度,实际只记录:遍历原2维数组时当前行的上一行
m //= 10
dp = [0 for _ in range(m + 1)] # 总钱数为0,1,2...m
goods = [None, ]
for i in range(1, N + 1):
p, w, b = list(map(int, input().split(" ")))
good = Good(i, p // 10, w * p, b) # 题目说商品价格为10的整数倍
goods.append(good)
for good in goods[1:]: # 遍历商品,将所有附件添加到对应主件的attach中
if good.belong != 0:
goods[good.belong].add_attach(good)
for good in goods[1:]:
if good.belong == 0: # 遍历主件
for j in reversed(range(m + 1)):
if j >= good.price:
dp[j] = max(dp[j], dp[j - good.price] + good.weight)
# 根据主件拥有附件的个数,判断怎么买让满意度最大
if len(good.attach) == 0:
continue
elif len(good.attach) == 1:
attach1 = good.attach[0]
# 不买;主;主+附1
if j >= good.price + attach1.price:
dp[j] = max(
dp[j],
dp[j-good.price-attach1.price] + good.weight + attach1.weight,
)
elif len(good.attach) == 2:
attach1 = good.attach[0]
attach2 = good.attach[1]
# 不买;主;主+附1;主+附2;主+附1+附2
if (j >= good.price + attach1.price):
dp[j] = max(
dp[j],
dp[j-good.price-attach1.price] + good.weight + attach1.weight,
)
if (j >= good.price + attach2.price):
dp[j] = max(
dp[j],
dp[j-good.price-attach2.price] + good.weight + attach2.weight,
)
if (j >= good.price + attach1.price + attach2.price):
dp[j] = max(
dp[j],
dp[j-good.price-attach1.price-attach2.price] + good.weight + \
attach1.weight + attach2.weight,
)
else:
break
print(dp[m])
except:
break
用时:7h
华为笔试刷题 文章被收录于专栏
高质量题: 1~40:HJ16,HJ22,HJ24,HJ26,HJ27,HJ28,HJ35,HJ37,HJ39; 40~80:HJ41,HJ42,HJ43,HJ44,HJ48,HJ50,HJ52,HJ53,HJ57,HJ61,HJ63,HJ64,HJ70,HJ71,HJ74,HJ77; 80~108:HJ82,HJ85,HJ88,HJ89,HJ93,HJ95,HJ98,HJ103,HJ107
