输入的第 1 行,为两个正整数N,m,用一个空格隔开:
(其中 N ( N<32000 )表示总钱数, m (m <60 )为可购买的物品的个数。)
从第 2 行到第 m+1 行,第 j 行给出了编号为 j-1 的物品的基本数据,每行有 3 个非负整数 v p q
(其中 v 表示该物品的价格( v<10000 ), p 表示该物品的重要度( 1 ~ 5 ), q 表示该物品是主件还是附件。如果 q=0 ,表示该物品为主件,如果 q>0 ,表示该物品为附件, q 是所属主件的编号)
n,m = map(int,input().split())
mainThing = {}
attach = {}
for i in range(1,m+1):
v,p,q = map(int,input().split())
if q==0:# 存储主件
mainThing[i] = [v,p]
else: # 存储附件
if q in attach:# 存储第2个附件
attach[q].append([v,p])
else:# 存储第1个附件
attach[q] = [[v,p]]
"""
dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]]+v[i])
dp[i]只依赖dp[i-1],状态转移方程就可以改为:
dp[j] = max(dp_pre[j], dp_pre[j-w[i]]+v[i])
dp_pre[j]存储上一次得到的值,现在只需要2*n的空间就能得到结果。
继续观察可以发现,其实只用一个一维dp数组就行,不需要额外的辅助数组。
让j从n到1遍历,此时每次更新的dp[j]时,max函数中dp[j]和 dp[j-w[i]]都是上次保存的值。
状态转移方程变为:
for j in [n...1]:
dp[j] = max(dp[j], dp[j-w[i]]+v[i])
如果从1到n遍历的话dp[j-w[i]]不能保证还是上次的值,
这也进一步说明为什么用一维数组时需要从n到1遍历。
"""
dp = [0]*(n+1)
for k in mainThing:
w,val = [],[]
w.append(mainThing[k][0])#1、主件
val.append(mainThing[k][0]*mainThing[k][1])
if k in attach:# 存在附件
w.append(w[0]+attach[k][0][0])#2、主件+附件1
val.append(val[0]+attach[k][0][0]*attach[k][0][1])
if len(attach[k])>1:#存在两附件
w.append( w[0]+attach[k][1][0])#3、主件+附件2
val.append(val[0]+attach[k][1][0]*attach[k][1][1])
w.append( w[0]+attach[k][0][0]+attach[k][1][0])#4、主件+附件2+附件1
val.append(val[0]+attach[k][0][0]*attach[k][0][1]+attach[k][1][0]*attach[k][1][1])
for j in range(n,-1,-10):
for k in range(len(w)):
if j-w[k]>=0:
dp[j] = max(dp[j], dp[j-w[k]]+val[k])
print(dp[n])