这题01背包,表示不知为何一眼切。。。
一维DP,每组数据两次DP。
算了,讲清楚一点吧。
我们对于每个u,v,d
将其拆成
1u,1v
2u,2v
4u,4v
…
d-(2k-1)u,d-(2k-1)v
例如d=17
我们便可以拆成:
1u,1v
2u,2v
4u,4v
8u,8v
2u,2v(这个是剩下的)
这样子就没错了。
然后就来一遍01背包搞搞就可以了。
详见看标:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int T,n,m,p,a[1410][2],b[1410][3];
int t,u,v,k,x,tot=0,cnt=0,f[50010],g[50010],big,ans;
inline int read()
{
int x=0; char c=getchar();
while (c<'0' || c>'9') c=getchar();
while (c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x;
}
int main()
{
freopen("food.in","r",stdin);
// freopen("food.out","w",stdout);
T=read();
while (T--)
{
n=read(),m=read(),p=read();
tot=cnt=0;
for (int i=1;i<=n;i++)
{
t=read(),u=read(),v=read(),k=1;
while (v-k>=0)
{
a[++tot][0]=t*k,a[tot][1]=u*k;
v-=k,k<<=1;
}
if (v) a[++tot][0]=t*v,a[tot][1]=u*v;
}
for (int i=1;i<=m;i++)
{
t=read(),u=read(),v=read(),k=1;
while (v-k>=0)
{
b[++cnt][0]=t*k,b[cnt][1]=u*k;
v-=k,k<<=1;
}
if (v) b[++cnt][0]=t*v,b[cnt][1]=u*v;
}
memset(f,10,sizeof(f)),f[0]=0;
for (int i=1;i<=tot;i++)
{
for (int j=p-1;j>=p-a[i][0];j--)
f[p]=min(f[p],f[j]+a[i][1]);
for (int j=p-a[i][0]-1;j>=0;j--)
f[j+a[i][0]]=min(f[j+a[i][0]],f[j]+a[i][1]);
}
big=f[p];
if (big==f[p+1]) {puts("TAT"); continue;}
memset(g,0,sizeof(g));
for (int i=1;i<=cnt;i++)
{
for (int j=big-1;j>=big-b[i][1];j--)
g[big]=max(g[big],g[j]+b[i][0]);
for (int j=big-b[i][1]-1;j>=0;j--)
g[j+b[i][1]]=max(g[j+b[i][1]],g[j]+b[i][0]);
}
for (int i=1;i<=50000;i++)
if (g[i]>=big) {printf("%d
",i); break;}
}
return 0;
}