分组背包的实质还是组合数问题,只不过有一些限制
多重背包其实是分组背包的一个特殊形式
金明的预算方案
这就是纯粹的分组背包
就是将里面的选择买什么当作一个决策,每组只能选择一种决策
就比如这里的蓝的代表主件,跟它相连的就是附件
然后每个主件及其附件看成一组,然后找出来有多少个决策,每个决策就是组中的一个情况,就相当于分组背包,每个只能选一种决策
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define PII pair<int, int>
#define x first
#define y second
const int N = 32010;
int n, m;
PII mas[N];
vector<PII> ser[N];
int f[N];
int main()
{
cin >> m >> n;
for(int i=1; i<=n; i++)
{
int v, w, q;
cin >> v >> w >> q;
if(!q) mas[i] = {v, v * w};
else ser[q].push_back({v, v * w});
}
for(int i=1; i<=n; i++)
{
if(mas[i].x)//并不是1~n都是主件,有的是附件,上面没有离散化,所以这里就直接看看价值是不是0,是0就跳过
{
for(int j = m; j>=0; j--)
{
for(int p = 0; p < 1 << ser[i].size(); p++)//2的n次方种策略
{
int v = mas[i].x, w = mas[i].y;
for(int q = 0; q < ser[i].size(); q++)//枚举每个附件
{
if (p >> q & 1)//用二进制来表示有没有
{
v += ser[i][q].x;
w += ser[i][q].y;
}
}
if (j >= v) f[j] = max(f[j], f[j - v] + w);
}
}
}
}
cout << f[m] << endl;
return 0;
}
开心的金明
01背包
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
const int N = 30010;
int n, m;
int f[N];
int main()
{
cin >> m >> n;
for (int i = 1; i <= n; i ++ )
{
int v, w;
cin >> v >> w;
w *= v;
for(int j = m; j>=v; j--)
{
f[j] = max(f[j], f[j - v] + w);
}
}
cout << f[m] << endl;
return 0;
}