题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5445
参考来源:http://blog.youkuaiyun.com/mr_xujh/article/details/48435527
题面:
Food Problem
Time Limit: 3000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 299 Accepted Submission(s): 106
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.
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.
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
Source
解题:
核心部分就是一个多重背包,通过将物品合并,极大地降低了复杂度,实现了优化。不过这道题转了两个弯,先要求出达到或大于能量需求的最小体积,再求出达到或大于最小体积的最小花费。虽然不是很难,但转了两个弯,让我自己写,目前是不大可能写出来的,代码是完全依瓢画葫芦按这位Mr_Xujh的代码写的,加了些注释。
代码:
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
struct dessert
{
int energy,space;
void add(int x,int y)
{
energy=x,space=y;
}
}store[2000];
//2000是因为最多200种甜点,而每种甜点数量不超过100,拆分成2的倍数,10个肯定够了
struct truck
{
int size,cost;
void add(int x,int y)
{
size=x;
cost=y;
}
}info[2000];
//2000同上
int min(int a,int b)
{
return a<b?a:b;
}
int max(int a,int b)
{
return a>b?a:b;
}
int minv,minc;//满足能量大于等于p的最小体积,满足体积大于等于minv的最小花费
int dp1[50105],dp2[50010];
//dp1[x]能量为x时的最小体积,dp2[x]花费为x时的最大体积
int main()
{
int cas,n,m,p,t,u,v,k,x,y,z,cnt1,cnt2;
scanf("%d",&cas);
while(cas--)
{
scanf("%d%d%d",&n,&m,&p);
//初始化
cnt1=cnt2=0;//俩下标
memset(dp1,0x3f,sizeof(int)*(p+101));
memset(dp2,0,sizeof(int)*(50010));
minv=1e9;
minc=1e9;
for(int i=1;i<=n;i++)
{
scanf("%d%d%d",&t,&u,&v);
k=1;
//多重背包的核心部分,将同种物品以特定规则合成新的物品,降低复杂度
while(k<v)
{
store[cnt1++].add(k*t,k*u);
v-=k;
//分别为1,2,4...任何数量皆可由这些数量拼接而成
k<<=1;
}
//仍有剩余,再装新形成一个物品
if(v)
store[cnt1++].add(v*t,v*u);
}
dp1[0]=0;
//遍历新形成的物品
for(int i=0;i<cnt1;i++)
//p+100是因为一个物品最多产生100的能量差异
for(int j=p+100;j>=store[i].energy;j--)
{
//当前达到当前能量体积最小值等于当前值和选择这个物品的最小值
dp1[j]=min(dp1[j],dp1[j-store[i].energy]+store[i].space);
//如果当前能量大于等于p,且体积更小则更新
if(j>=p&&dp1[j]<minv)
minv=dp1[j];
}
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&z);
k=1;
//同上,重组物品
while(k<z)
{
info[cnt2++].add(k*x,k*y);
z-=k;
k<<=1;
}
if(z)
info[cnt2++].add(z*x,z*y);
}
for(int i=0;i<cnt2;i++)
for(int j=50000;j>=info[i].cost;j--)
{
//使用j花费所能达到的最大体积
dp2[j]=max(dp2[j],dp2[j-info[i].cost]+info[i].size);
//如果当前花费下体积大于等于最小需求体积,且花费小于最小花费,则更新
if(dp2[j]>=minv&&j<minc)
minc=j;
}
//如果最小花费大于50000,输出TAT,否则输出最小值
if(minc>50000)printf("TAT\n");
else printf("%d\n",minc);
}
return 0;
}