1025 队伍配置 01背包变式
链接:https://ac.nowcoder.com/acm/contest/24213/1025
来源:牛客网
题目描述
队伍配置里,可供玩家选择的作战人物被称作“从者”,玩家可以对每个“从者”可以装备至多1件的“概念礼装”,玩家具有一个cost上限值。详细定义如下:
1、 每个从者和概念礼装都具有攻击值ATK。
2、 每个从者和概念礼装都会占据一定的cost值。
3、 每个从者和概念礼装只能上场一次,不能重复使用。
4、 概念礼装只能装备在从者上,不能单独存在。
5、 选择的从者和概念礼装的cost值之和不能超过玩家的cost上限值。
6、 最多可以选择5名从者(在cost值限制下)。
现在给出玩家仓库的每个从者和每件概念礼装的ATK值和cost值,问在满足定义的条件下,队伍可以凑出的最大ATK值。
输入描述:
输出描述:
输出一行,一个整数,代表可以凑出的最大ATK值。
分析
普通的01背包:n件物品,在体积V,能选择的最大价值。dp数组:f[i][j] i件物品,体积最多为j的最大价值
该题,n件主件,m件附件,附件的选择数量小于主件,总金钱数为d ,问最大价值
条件:
1.每件物品的花费 总量不能超过上限
2.附件数量不超过主件
3.主件最多5个,附件最多主件个
条件统计下,我们可以用一个dp数组将这些条件全部包揽条件统计下,我们可以用一个dp数组将这些条件全部包揽
可以看出没有附件的话,就是01背包了,由于主件和附件数量关系是限制条件,所以都要处理。设dp数组为:f[m][i][j][k] 表示从m件物品中选择,i元钱,j件主件,k件附件的最大价值。
但其实,对于n和m我们可以用滚动数组转移,不需要多占用一维。dp数组转移:f[i][j][k] 表示i元钱,j件主件,k件附件的最大价值。
同时主件数量少,最多只有五件。附件依附于主件
总之,可以先把主件处理出来再处理附件。
处理主件:
先假设k=0的时候进行转移,最多5个主件,j最大为5先假设k=0的时候进行转移,最多5个主件,j最大为5
用一个01背包,更新完所有k等于0时候的状态用一个01背包,更新完所有k等于0时候的状态
不过有点不一样,和01背包唯一的区别就是需要维护一个有几个主件的状态
状态转移:f[i][j][k] = max(f[i][j][k],f[i-v][j-1][0]+w);
处理附件:
四重循环,循环每个附件,价格,主件数量,附件数量
状态转移f[i][j][k] = max(f[i][j][k],f[i-v][j][k-1] + w)
答案要对于每一个状态取一个最大值
背包问题:就是选择问题?
//-------------------------代码----------------------------
#define int LL
const int N = 1e5+10;
int n,m,d;
int f[200][300][300];
void solve()
{
cin>>n>>m>>d;
LL ans = 0;
fo(i,1,n) {
int x,y;cin>>x>>y;
of(j,d,y) {
fo(k,1,5) {
f[j][k][0] = max(f[j][k][0],f[j-y][k-1][0]+x);
ans = max(ans,f[j][k][0]);
}
}
}
fo(i,1,m) {
int x,y;cin>>x>>y;
of(j,d,y) {
fo(k,1,5) {
fo(l,1,k) {
f[j][k][l] = max(f[j][k][l],f[j-y][k][l-1]+x);
ans = max(ans,f[j][k][l]);
}
}
}
}
cout<<ans<<endl;
rt;
}
signed main(){
clapping();TLE;
// int t;cin>>t;while(t -- )
solve();
// {solve(); }
return 0;
}
/*样例区
*/
//------------------------------------------------------------