传送门:金明的预算方案
思路:每一个主件最多有四种状态,相当于一个分组,有p,p+a,p+b,p+a+b这四个物品。j>>k&1等于j的二进制的第k位,当该组件的附件为0时不会进入循环,选择的物品就是p。j<1<<servent[i].size()相当于在前j个物品里面,如果是j<servent[i].size()会出错。
代码:
#include <bits/stdc++.h>
#define v first
#define w second
using namespace std;
int n,m;
typedef pair<int, int> PII;
const int N=32010;
PII master[60];
vector<PII> servent[60];
int f[N];
int main()
{
cin>>m>>n;
for(int i=1;i<=n;i++)
{
int a,b,c;
cin>>a>>b>>c;
b*=a;
if(!c) master[i]={a,b};
else servent[c].push_back({a,b});
}
for(int i=1;i<=n;i++)
for(int u=m;u>=0;u--)
{
for(int j=0;j<1<<servent[i].size();j++)
{
int v=master[i].v,w=master[i].w;
for(int k=0;k<servent[i].size();k++)
if(j>>k&1)
{
v+=servent[i][k].v;
w+=servent[i][k].w;
}
if(u>=v) f[u]=max(f[u],f[u-v]+w);
}
}
cout<<f[m]<<endl;
return 0;
}