P1064 [NOIP2006 提高组] 金明的预算方案
时间:2023.11.19
题目地址:[NOIP2006 提高组] 金明的预算方案
题目分析
动态规划的0-1背包,采用动态数组。如果不了解的话,可以先看看这个背包DP。
这个是0-1背包的标准状态转移方程
f
[
j
]
=
m
a
x
(
f
[
j
−
w
[
i
]
]
+
v
[
i
]
,
f
[
j
]
)
f[j] = max(f[j-w[i]] + v[i], f[j])
f[j]=max(f[j−w[i]]+v[i],f[j])。那么就基于对这个方程进行展开。
五种情况:
① 不放。
m
a
x
(
)
max()
max()
② 放主物品,不带副品。
f
[
j
]
=
f
[
j
]
=
m
a
x
(
f
[
j
−
m
a
i
n
_
a
r
t
[
i
]
[
0
]
]
+
m
a
i
n
_
a
r
t
[
i
]
[
1
]
,
f
[
j
]
)
f[j] = f[j] = max(f[j-main\_art[i][0]] + main\_art[i][1], f[j])
f[j]=f[j]=max(f[j−main_art[i][0]]+main_art[i][1],f[j])
③ 放主物品,带1副品。
f
[
j
]
=
m
a
x
(
f
[
j
]
,
f
[
j
−
m
a
i
n
_
a
r
t
[
i
]
[
0
]
−
r
a
l
_
a
r
t
[
i
]
[
1
]
[
0
]
]
+
m
a
i
n
_
a
r
t
[
i
]
[
1
]
+
r
a
l
_
a
r
t
[
i
]
[
1
]
[
1
]
)
f[j] = max(f[j], f[j-main\_art[i][0]-ral\_art[i][1][0]] + main\_art[i][1] + ral\_art[i][1][1])
f[j]=max(f[j],f[j−main_art[i][0]−ral_art[i][1][0]]+main_art[i][1]+ral_art[i][1][1])。
④ 放主物品,带2副品。
f
[
j
]
=
m
a
x
(
f
[
j
]
,
f
[
j
−
m
a
i
n
_
a
r
t
[
i
]
[
0
]
−
r
a
l
_
a
r
t
[
i
]
[
2
]
[
0
]
]
+
m
a
i
n
_
a
r
t
[
i
]
[
1
]
+
r
a
l
_
a
r
t
[
i
]
[
2
]
[
1
]
)
f[j] = max(f[j], f[j-main\_art[i][0]-ral\_art[i][2][0]] + main\_art[i][1] + ral\_art[i][2][1])
f[j]=max(f[j],f[j−main_art[i][0]−ral_art[i][2][0]]+main_art[i][1]+ral_art[i][2][1])。
⑤ 放主物品,带1、2副品。
f
[
j
]
=
m
a
x
(
f
[
j
]
,
f
[
j
−
m
a
i
n
_
a
r
t
[
i
]
[
0
]
−
r
a
l
_
a
r
t
[
i
]
[
1
]
[
0
]
−
r
a
l
_
a
r
t
[
i
]
[
2
]
[
0
]
]
+
m
a
i
n
_
a
r
t
[
i
]
[
1
]
+
r
a
l
_
a
r
t
[
i
]
[
1
]
[
1
]
+
r
a
l
_
a
r
t
[
i
]
[
2
]
[
1
]
)
f[j] = max(f[j], f[j-main\_art[i][0]-ral\_art[i][1][0]-ral\_art[i][2][0]] + main\_art[i][1] + ral\_art[i][1][1] + ral\_art[i][2][1])
f[j]=max(f[j],f[j−main_art[i][0]−ral_art[i][1][0]−ral_art[i][2][0]]+main_art[i][1]+ral_art[i][1][1]+ral_art[i][2][1])。
这些理解清楚了就简单了。
但是超时了三个,enmm…,有点那啥,主要是理解思路和过程,掌握方法好吧。
代码
n, m = map(int, input().split())
main_art = [[] for _ in range(m+1)]
ral_art = [[0, [0]*2, [0]*2] for _ in range(m+1)]
# 例:[[0, [0, 0], [0, 0]], [1, [300, 600], [0,0]], [2, [200, 400], [100, 400]]]
for i in range(1, m+1):
v, p, q = map(int, input().split())
if q == 0:
main_art[i] = [v, p*v]
else:
ral_art[q][0] += 1
ral_art[q][ral_art[q][0]][0] = v
ral_art[q][ral_art[q][0]][1] = v*p
f = [0]*(n+1)
for i in range(1, m+1):
if not main_art[i]:
continue
for j in range(n, main_art[i][0]-1, -1):
f[j] = max(f[j-main_art[i][0]] + main_art[i][1], f[j])
if j >= main_art[i][0] + ral_art[i][1][0]: # 判断剩余钱(空间)能否买(放)这个物品。
f[j] = max(f[j], f[j-main_art[i][0]-ral_art[i][1][0]] + main_art[i][1] + ral_art[i][1][1])
if j >= main_art[i][0] + ral_art[i][2][0]: # 判断剩余钱(空间)能否买(放)这个物品。
f[j] = max(f[j], f[j-main_art[i][0]-ral_art[i][2][0]] + main_art[i][1] + ral_art[i][2][1])
if j >= main_art[i][0] + ral_art[i][1][0] + ral_art[i][2][0]: # 判断剩余钱(空间)能否买(放)这个物品。
f[j] = max(f[j], f[j-main_art[i][0]-ral_art[i][1][0]-ral_art[i][2][0]] + main_art[i][1] + ral_art[i][1][1] + ral_art[i][2][1])
print(f[n])