链接:http://acm.hdu.edu.cn/showproblem.php?pid=3182
预处理+dp
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=15;
int val[N],cost[1<<N],energy[N],last[N];
int dp[1<<N];
int n,m;
void init()
{
memset(last,0,sizeof(last));
memset(cost,0,sizeof(cost));
memset(dp,-1,sizeof(dp));
for(int i=0;i<(1<<n);i++)//预处理 cost[i]记录i状态需要的energy
{
for(int j=0;j<n;j++)
{
if(i&(1<<j))
cost[i]+=energy[j];
}
}
}
bool ok(int x,int p)
{
if((x&last[p])==last[p]&&cost[x]+energy[p]<=m)//判断x状态是否满足p汉堡的前置条件&&x状态所需能量值+p所需能量值<=总能量值
return true;
return false;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++) scanf("%d",&val[i]);
for(int i=0;i<n;i++) scanf("%d",&energy[i]);
init();
for(int i=0;i<n;i++)
{
int x,y;
scanf("%d",&x);
while(x--)
{
scanf("%d",&y);
y--;
last[i]|=1<<y;
}
}
int ans=0;
dp[0]=0;
for(int i=0;i<(1<<n);i++)
{
if(dp[i]==-1) continue;//如果i状态所需能量值超过上限 continue
for(int j=0;j<n;j++)
{
if(ok(i,j)&&(i&(1<<j))==0)
{
dp[(1<<j)|i]=dp[i]+val[j];
ans=max(dp[(1<<j)|i],ans);
}
}
}
printf("%d\n",ans);
}
return 0;
}