看到题目就想到5维背包,不过想了想状态转移要5层循环,写起来相当痛苦。也没想到6进制,看了一下讨论说用六进制,想了一下似乎还真是这样,状态转换好写起来就简单,直接背包就可以。
ACcode:
#include<cstdio>
#include<cstring>
const int NS=6;
const int MAX=7776;
const int INF=1<<30;
struct offer
{
int st,p;
void inpt(int xa,int xb){
st=xa,p=xb;
}
}s[110];
int n,top,ans;
int x,y,z,m,num;
int p6[NS];
int h[1000];
int dp[MAX];
int bit[MAX][5];
void prepare()
{
p6[0]=1;
for (int i=1;i<NS;i++)
p6[i]=p6[i-1]*6;
for (int i=0;i<MAX;i++)
for (int t=i,j=0;j<5;j++)
bit[i][j]=t%6,t/=6;
}
int judge(int s1,int s2)
{
for (int i=0;i<5;i++)
if (bit[s2][i]>bit[s1][i]) return 0;
return 1;
}
int Min(int xa,int xb)
{
return xa<xb?xa:xb;
}
int main()
{
prepare();
while (~scanf("%d",&n))
{
top=ans=dp[0]=0;
for (int i=0;i<n;i++)
{
scanf("%d%d%d",&x,&y,&z);
ans+=y*p6[i],h[x]=i;
s[top++].inpt(p6[i],z);
}
scanf("%d",&m);
for (int i=0;i<m;i++)
{
scanf("%d",&num),z=0;
for (int j=0;j<num;j++)
scanf("%d%d",&x,&y),z+=p6[h[x]]*y;
scanf("%d",&x); s[top++].inpt(z,x);
}
for (int i=1;i<=ans;i++)
{
dp[i]=INF;
for (int j=0;j<top;j++)
if (judge(i,s[j].st))
dp[i]=Min(dp[i],dp[i-s[j].st]+s[j].p);
}
printf("%d\n",dp[ans]);
}
return 0;
}