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;
}
本文深入解析了一种经典的算法问题——多重背包问题,通过实例详细介绍了如何利用二进制拆分和完全背包策略来解决该问题。文章重点在于如何在满足特定条件(如美味度超过某一阈值)下,寻找最优解决方案(如最低费用)。同时,文中还包含了一段完整的C++代码实现,有助于读者理解和应用。
718

被折叠的 条评论
为什么被折叠?



