您的位置:首页 > 其它

HDU 5445——Food Problem——————【多重背包】

2015-09-24 12:26 239 查看

Food Problem

Time Limit: 3000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 660 Accepted Submission(s): 196


[align=left]Problem Description[/align]
Few days before a game of orienteering, Bell came to a mathematician to solve a big problem. Bell is preparing the dessert for the game. There are several different types of desserts such as small cookies, little grasshoppers and tiny mantises. Every type of dessert may provide different amounts of energy, and they all take up different size of space.

Other than obtaining the desserts, Bell also needs to consider moving them to the game arena. Different trucks may carry different amounts of desserts in size and of course they have different costs. However, you may split a single dessert into several parts and put them on different trucks, then assemble the parts at the game arena. Note that a dessert does not provide any energy if some part of it is missing.

Bell wants to know how much would it cost at least to provide desserts of a total energy of p (most of the desserts are not bought with money, so we assume obtaining the desserts costs no money, only the cost of transportation should be considered). Unfortunately the mathematician is having trouble with her stomach, so this problem is left to you.

[align=left]Input[/align]
The first line of input contains a integer T(T≤10) representing the number of test cases.

For each test case there are three integers n,m,p on the first line (1≤n≤200,1≤m≤200,0≤p≤50000), representing the number of different desserts, the number of different trucks and the least energy required respectively.

The i−th of the n following lines contains three integers ti,ui,vi(1≤ti≤100,1≤ui≤100,1≤vi≤100) indicating that the i−th dessert can provide tienergy, takes up space of size ui and that Bell can prepare at most vi of them.

On each of the next m lines, there are also three integers xj,yj,zj(1≤xj≤100,1≤yj≤100,1≤zj≤100) indicating that the j−th truck can carry at most size of xj , hiring each one costs yj and that Bell can hire at most zj of them.

[align=left]Output[/align]
For every test case output the minimum cost to provide the dessert of enough energy in the game arena if it is possible and its cost is no more than 50000. Otherwise, output TAT on the line instead.

[align=left]Sample Input[/align]

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

[align=left]Sample Output[/align]

4
14

12

TAT

[align=left]Source[/align]
2015 ACM/ICPC Asia Regional Changchun Online

题目大意:T组测试数据。给你n种食物,m种货车,p表示询问运送不少于p能量值的食物最少需要的运费。然后给你n种食物的能量值energy,食物的体积大小size,这种食物的份数amount。然后m种货车,每种货车能运送的体积siz,运费cost,这种车有多少辆number。如果运费多于5W或者不能达到运送的要求,输出TAT。

解题思路:两次多重背包。第一次定义dp[j]=min(dp[j],dp[j-k*energy]+size*k)表示能量为j时需要的最少空间。第二次定义dp[j]=max(dp[j],dp[j-k*size]+k*number)。表示运费为j时最大运输量。对于能量的背包最大容量,我们取所有食物的能量和与50000的最小值。对于花费的背包最大容量,我们取所有货车的花费和与50000的最小值。最后需要从p到取的能量的最小值中找一个最小的值作为阀值,找出最小不小于阀值的花费。

#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
struct Cake{
int energy,siz,amont;
}cakes[220];
struct Truck{
int siz,cost,num;
}trucks[220];
int dp1[55000],dp2[55000];
void ZeroOnePack(int cost,int weight,int V,int *dp,int typ){
if(typ==1)
for(int i=V;i>=cost;i--){
dp[i]=min(dp[i],dp[i-cost]+weight);
}
else
for(int i=V;i>=cost;i--){
dp[i]=max(dp[i],dp[i-cost]+weight);
}
}
void CompletePack(int cost,int weight,int V,int *dp,int typ){
if(typ==1)
for(int i=cost;i<=V;i++){
dp[i]=min(dp[i],dp[i-cost]+weight);
}
else
for(int i=cost;i<=V;i++){
dp[i]=max(dp[i],dp[i-cost]+weight);
}
}
void MultiplePack(int cost,int weight,int amount,int V,int *d,int typ){
if(cost*amount>=V){
CompletePack(cost,weight,V,d,typ);
return ;
}
int k=1;
while(amount>k){
ZeroOnePack(cost*k,weight*k,V,d,typ);
amount-=k;
k*=2;
}
ZeroOnePack(cost*amount,weight*amount,V,d,typ);
}
int main(){
int T,n,m,p;
scanf("%d",&T);
while(T--){
memset(dp1,INF,sizeof(dp1));
memset(dp2,0,sizeof(dp2));
dp1[0]=0;
int vv=0,cc=0;
scanf("%d%d%d",&n,&m,&p);
for(int i=1;i<=n;i++){
scanf("%d%d%d",&cakes[i].energy,&cakes[i].siz,&cakes[i].amont);
vv+=cakes[i].energy*cakes[i].amont;
}
for(int i=1;i<=m;i++){
scanf("%d%d%d",&trucks[i].siz,&trucks[i].cost,&trucks[i].num);
cc+=trucks[i].cost*trucks[i].num;
}
vv=min(50000,vv);
for(int i=1;i<=n;i++){
MultiplePack(cakes[i].energy,cakes[i].siz,cakes[i].amont,vv,dp1,1);
}
cc=min(cc,50000);
for(int i=1;i<=m;i++){
MultiplePack(trucks[i].cost,trucks[i].siz,trucks[i].num,cc,dp2,2);
}
int pos=0;
int tmp=INF;
for(int i=p;i<=vv;i++){
tmp=min(dp1[i],tmp);
}
for(int i=1;i<=cc;i++){
if(dp2[i]>=tmp){
pos=i; break;
}
}
if(pos==0){
printf("TAT\n");
}else{
printf("%d\n",pos);
}
}
return 0;
}

/*
555
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

*/


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: