【洛谷】依赖背包 P1064 金明的预算方案
题目大意
给出 m 件物品,每件物品有三个属性:\(a,b,c\),分别表示该物品的价格,重要度,以及是主件还是附件,如果是附件给出的是主件是哪个。
现在有限制:如果要取附件,一定要取主件,并且同一个主件附件最多取两个。
定义每个物品的价值为 价格*重要度,现在有 n 元钱,问可以买的最大价值是多少。
思路
把附件和主件捆绑在一起,形成新的物品。
把每个主件可以形成的物品放到同一个组中,做分组背包即可。
代码
#include<bits/stdc++.h>
using namespace std;
#define pb push_back
typedef long long ll;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
const int seed=233;
const int N=4e4+10;
int w[100],v[100],dp[N];
vector<int>vec[100];
vector<pair<int,int>>thi[N];
int main()
{
int n,m;
scanf("%d%d",&n,&m);
int cnt=0;
for(int i=1;i<=m;i++){
int fa;
scanf("%d%d%d",&w[i],&v[i],&fa);
v[i]*=w[i];
vec[fa].push_back(i);
if(!fa)
thi[i].pb(make_pair(w[i],v[i]));
}
for(int i=1;i<=m;i++){
if(!vec[i].size()) continue;
for(int j=0;j<vec[i].size();j++){
thi[i].pb(make_pair(w[vec[i][j]]+w[i],v[vec[i][j]]+v[i]));
for(int k=j+1;k<vec[i].size();k++)
thi[i].pb(make_pair(w[vec[i][j]]+w[vec[i][k]]+w[i],v[vec[i][j]]+v[vec[i][k]]+v[i]));
}
}
for(int i=1;i<=m;i++){
if(!thi[i].size()) continue;
for(int j=n;j>=0;j--){
for(int k=0;k<thi[i].size();k++){
if(j>=thi[i][k].first)
dp[j]=max(dp[j],dp[j-thi[i][k].first]+thi[i][k].second);
}
}
}
printf("%d\n",dp[n]);
return 0;
}