Description
Input
Output
Sample Input
4
1 1 7
14 2 1
1 2 2
1 1 10
10 10 1
5 7 2
5 3 34
1 4 1
9 4 2
5 3 3
1 3 3
5 3 2
3 4 5
6 7 5
5 3 8
1 1 1
1 2 1
1 1 1
Sample Output
4
14
12
TAT
Data Constraint
纪中题解:
个人补充:
本题是个多重背包
由于(题解 )食物可以拆开运输(用二进制拆分),我们可以看出美味度和费用分别是两个条件,所以我们需要两个完全背包。
而两个背包也有两个不同的物品:食物和运载工具。食物的3个属性:ti美味度;ui大小;vi数量。而运载工具也有3个属性:xi容量;yi费用;zi次数。食物背包需要费用换美味值,工具背包需要美味值换费用。要求美味值超过p的情况下费用最低。
对于食物背包,求出美味度≥p的空间最小的食物的大小ans1,我们用g[i]表示当前美味度为i所需空间的大小,假如费用i≥p则判断,用g[i]更新ans1的值。
若对于食物背包,能够求出ans1,那么就代表数据给的食物可以满足美味值的要求,接下来就只用找,满足美味值的条件下,最小费用的情况。最后不要忘记当不满足其中一个条件时要输“TAT”
PS:
蓬莱山辉夜出自上海爱丽丝幻乐团出品的《东方project》系列中的《东方永夜抄》,是月都的公主,也叫做辉夜姬neet姬
感觉这题的角色设定有点问题啊,辉夜就是neet啊,吃东西不是幽幽子sama的事吗?(;´д`)ゞ
就是这位↓(图转自p站画师えふぇ的作品:ダコ夜)
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1250,M=51050;
int uu[N],tt[N],x[N],y[N],z[N],f[N][M],g[M];
int sum,n,m,p,test,ans1,ans2;
int main(){
scanf("%d",&test);
for (int h=1; h<=test; h++){
memset(f,0,sizeof(f));
memset(g,0x3f,sizeof(g));
sum=0;
scanf("%d%d%d",&n,&m,&p);
for(int i=1;i<=n;i++){
int t,u,v;
scanf("%d%d%d",&t,&u,&v);
for(int j=1; j<=v; j*=2){//2进制拆分
v-=j;
uu[++sum]=u*j;
tt[sum]=t*j;
}
if(v) uu[++sum]=u*v,tt[sum]=t*v;//如还有剩余,则将剩余的也当成一块进行运输
}
g[0]=0;ans1=2147483647;
for(int i=1; i<=sum; i++)
for(int j=p+100; j>=tt[i]; j--){
g[j]=min(g[j],g[j-tt[i]]+uu[i]);
if(j>=p) ans1=min(ans1,g[j]);
}
if(ans1==2147483647){printf("TAT\n"); continue;}
for(int i=1; i<=m; i++)
scanf("%d%d%d",&x[i],&y[i],&z[i]);
ans2=2147483647;
for(int i=1; i<=m; i++)
for(int j=0; j<=z[i]; j++)
for(int k=1; k<=M-10; k++)
if(y[i]*j<=k){
f[i][k]=max(f[i][k],f[i-1][k-y[i]*j]+x[i]*j);
if(f[i][k]>=ans1) {ans2=min(ans2,k);break;}
}
if(ans2==2147483647){printf("TAT\n"); continue;}
printf("%d\n",ans2);
}
return 0;
}