- 空門蒼负责的祭典人手不够了,现在她需要求助你会。可惜的是,你会人手也不够了,所以你会会长yyh需要女装来纳新。
现有n个职位,每个职位只能纳一个人,这届有m个萌新,每个萌新只能胜任一个职位,每个萌新都有自己的实力值与需求值,你会会长可以通过女装来满足他们的需求值,但你会会长最多也只能满足s的需求值(即纳到的萌新需求值≤s),在社长的能力范围之内,要让纳到的萌新实力值之和最大,问最大值为多少。
输入
第一行分别为 n,m,s
接下来有 m 行,每行有三个数字 x,y,z 分别代表这个萌新能胜任的位置(以数字 1-n 来表示),实力值,需求值
输出
输出为一个数字,代表最大的实力值之和
输入样例
3 9 10
1 4 2
1 7 5
1 8 10
2 6 2
2 7 2
2 8 2
3 4 6
3 7 7
3 8 2
输出样例
23
提示
对于20%的数据, m<=20, n<=20, s<=100
对于50%的数据, m<=500, n<=500, s<=1000
对于100%的数据, m<=5000, n<=5000, s<=5000
我相信你一眼就看出来这是道DP题
所以只要用分组背包的思路做就可以轻松AC了
分组背包和普通背包的差别:
这个问题变成了每组物品有若干种策略:
是选择本组的某一件,还是一件都不选。
也就是说设 f [ k ] [ j ] 表示前 k 组物品花费费用 j 能取得的最大权值,则有:
f[k][j]=max(f[k−1][j],f[k−1][j−c[i]]+w[i]∣物品i属于组k)
核心伪代码:
for (所有的组k)
for (int j = V; j >= 0; j--)
for (所有属于组k的i)
f[j] = max{f[j], f[j - w[i]] + v[i]}
注意这里的三层循环的顺序, f o r ( j . . . 0 )
这一层循环必须在 for (所有的 i 属于组 k)之外。
这样才能保证每一组内的物品最多只有一个会被添加到背包中。
另外,显然可以对每组内的物品应用完全背包中“一个简单有效的优化”。
- 小结
分组的背包问题将彼此互斥的若干物品称为一个组,这建立了一个很好的模型。
不少背包问题的变形都可以转化为分组的背包问题(例如有依赖的背包),由分组的背包问题进一步可定义“泛化物品”的概念,十分有利于解题。
以下是AC代码:
//By Mitruha
//Date : 2020 10 23
//分组背包
#include <bits/stdc++.h>
using namespace std;
const int Maxn = 5010;
int v[Maxn], w[Maxn];
int a[Maxn][Maxn];
int opt[Maxn];
int n, m, s, group;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n >> m >> s;
for(int i = 1;i <= m; i++)
{
cin >> group >> w[i] >> v[i];
a[group][++a[group][0]] = i;
}
for(int i = 0; i < s; i++)
for(int j = m ; j >= 0 ; j--)
for(int k = 1;k <= a[i][0]; k++)
if(j - v[a[i][k]] >= 0)
opt[j] = max(opt[j], opt[j - v[a[i][k]]] + w[a[i][k]]);
cout << opt[m] << "
";
return 0;
}