题目描述:
Problem Description
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.
Input
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 ti energy, 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.
Output
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.
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
题目分析:
有一些cookie,每一种cookie都有其特定的energy,但也要占特定的volume,每一种cookie都有数量num。同时你拥有一些运载cookie的truck,每种truck也可以装载特定volume的cookie,每种truck需要特定的prize,每种truck也有特定数量num。
求将所有cookie都装载在truck中,求花费最小的prize,如果不能讲所有cookie装满,输出“TAT”。
因为在cookie装在truck是只计算volume值的,就是说可以将一种cookie分别装在不同的truck上。
要进行两次的多重背包,第一次对cookie的energy进行一次多重背包,找出最小的volume值。第二次对truck的prize进行一次多重背包,找出最小的volume值。这两次多重背包的结果根据volume值建立联系。最后再根据找一遍prize得出最终的答案。
(ps:这题需要进行二进制优化 不然要TLE)
代码如下:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
const int INF = 0x3f3f3f3f;
const int MAXN =65000;
using namespace std;
int dp[MAXN];//在第一次中,dp[i]表示在获得energy为i时最小的vol体积
//在第二次中,dp[i]表示在花费prize为i时最小的vol体积
struct Cookie
{
int val,vol,t;
}cookie[220];
struct Truck
{
int vol,prize,t;
}truck[220];
int Mul_Pack1(Cookie cookie[], int n)//第一次多重背包
{
memset(dp,INF,sizeof(dp));
dp[0]=0;
for(int i=1; i<=n; i++)//遍历每一种cookie
{
int t=cookie[i].t;
for(int j=1; t>0; j<<=1)//寻找该种cookie选择次数
{
int tmp=min(t,j);//需要优化
for(int k=60000; k>=cookie[i].val*tmp; k--)//对其energy进行dp
{
dp[k]=min(dp[k-cookie[i].val*tmp]+cookie[i].vol*tmp,dp[k]);
}
t-=tmp;
}
}
}
int Mul_Pack2(Truck truck[],int n)
{
memset(dp,0,sizeof(dp));
for(int i=1; i<=n; i++)
{
int t=truck[i].t;
for(int j=1; t>0; j<<=1)
{//需要优化
int tmp=min(t,j);
for(int k=60000; k>=truck[i].prize*tmp; k--)
{
dp[k]=max(dp[k-truck[i].prize*tmp]+truck[i].vol*tmp,dp[k]);
}
t-=tmp;
}
}
}
int T;
int main()
{
int n,m,p;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&n,&m,&p);
for(int i=1; i<=n; i++)
scanf("%d%d%d",&cookie[i].val,&cookie[i].vol,&cookie[i].t);
for(int i=1; i<=m; i++)
scanf("%d%d%d",&truck[i].vol,&truck[i].prize,&truck[i].t);
Mul_Pack1(cookie,n);
int minv=INF;//记录最小体积
for(int i=p; i<=60000; i++)
{
minv=min(dp[i],minv);
}
if (minv==INF)
{
printf("TAT\n");
continue;
}
Mul_Pack2(truck,m);
bool f=false;
int num;
for(int i=1; i<=60000; i++)
{
if (dp[i]>=minv && dp[i]!=INF)
{
f=true;
num=i;
break;
}
}
if (f) printf("%d\n",num);
else printf("TAT\n");
}
return 0;
}