题目描述
Sample Input
n
(
[
1
,
3.2
e
4
]
)
m
(
[
1
,
60
]
)
n([1,3.2e4])\ m([1,60])
n([1,3.2e4]) m([1,60])
v
i
(
[
0
,
1
e
4
]
)
p
i
(
[
1
,
5
]
)
q
i
(
[
0
,
m
]
)
v_i([0,1e4]) \ p_i([1,5])\ q_i([0,m])
vi([0,1e4]) pi([1,5]) qi([0,m])
1000 5
800 2 0
400 5 1
300 5 1
400 3 0
500 2 0
Sample Output
小于等于2e5
2200
思路
将主件和附件捆绑起来。遍历到附件就跳过,只考虑主件是不是要放入。可能有5种选择:
- 不放入当前主件
- 只放入当前主件(在资金>主件价格的条件下)
- 放入当前主件+附件1(在该主件有1个附件或2个附件 && 资金 > 主件价格+附件1价格 的条件下)
- 放入当前主件+附件2(在该主件有2个附件 && 资金 > 主件价格+附件2价格 的条件下)
- 放入当前主件+附件1+附件2(在该主件有2个附件 && 资金 > 主件价格+附件1价格+附件2价格 的条件下)
AC代码
#include <iostream>
#include <algorithm>
using namespace std;
int n,m;
int f[32000]; // =320000/10 节省空间
int v[65];
int p[65];
int q[65];
int app[65][3]; //apo[i][j] = i号物品的第j个附件的编号,0<= j <=2
int appCt[65]; //appCt[i]的值 = i号物品的附件的数量
int main(){
cin >> n >> m; //总钱数 , 物品个数
n /= 10; //n是10的倍数,节省时间
for(int i = 1;i<=m;++i){
cin >> v[i]>>p[i]>>q[i];
v[i] /= 10;
if(q[i]!=0){ //当前物品是以q[i]为编号的物品的附件
appCt[q[i]]++;
app[q[i]][appCt[q[i]]] = i;
}
}
for(int i = 1;i<=m;++i){
for(int j = n; j>= v[i]; j--){
if(q[i] == 0){//分析的是主件
f[j] = max(f[j],f[j-v[i]] + p[i]*v[i]);
if(appCt[i] == 2){//可能有2个附件
if(j-v[i] >= v[app[i][1]])
f[j] = max(f[j],f[j-v[i] - v[app[i][1]]]
+ p[i]*v[i] + p[app[i][1]]*v[app[i][1]]);
if(j-v[i] >= v[app[i][2]])
f[j] = max(f[j],f[j-v[i] - v[app[i][2]]]
+ p[i]*v[i]
+ p[app[i][2]]*v[app[i][2]]);
if(j-v[i]>= v[app[i][1]] + v[app[i][2]])
f[j] = max(f[j],f[j-v[i] - v[app[i][1]]-v[app[i][2]]]
+ p[i]*v[i]
+ p[app[i][1]]*v[app[i][1]] + p[app[i][2]]*v[app[i][2]]);
}else if(appCt[i]==1){//可能会有1个附件
if(j-v[i] >= v[app[i][1]])
f[j] = max(f[j],f[j-v[i] - v[app[i][1]]]
+ p[i]*v[i]
+ p[app[i][1]]*v[app[i][1]]);
}
}
}
}
cout<<f[n]*10; //价格还原
return 0;
}