(JZ1274)2019.01.26【NOIP提高组】模拟B组 2.食物

食物

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;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值