1. 程式人生 > 實用技巧 >【洛谷】依賴揹包 P1064 金明的預算方案

【洛谷】依賴揹包 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;
}