【洛谷】依赖背包 P1064 金明的预算方案

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;
}
posted @ 2020-12-02 10:34  Valk3  阅读(85)  评论(0编辑  收藏  举报