Description
Input
第一行一个数test,表示有test组数据。
对于每组数据,第一行有3个整数n,m,p.
接下来n行,每行3个整数t,u,v,描述一种食物。
最后m行,每行3个整数x,y,z,描述一种运载工具。
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
test不会很大。
对于前20%的数据,n,m≤20.
对于前50%的数据,n,m≤30,ti,ui,vi,xi,yi,zi≤10.
Solution
我们看到这道题目很显然是背包问题,但是这道题的特别点在于食物可以被分开。那么只需要运输空间大于食物所需空间就能运输成功。
所以我们要打2个背包。
①求出美味度≥p的最小的食物的大小a1.
我们用g[i]表示当前美味度为i所需空间的大小。
假如费用i≥p则判断、用g[i]更新a1的值。
②求出可以装a1这么大的食物需要多少费用。
设f[i,k]表示装到第i件物品,所需费用为k所需最大空间。
如果f[i,k]≥a1,则证明我们运输当前的食物的美味度已经≥p了,那么>k的情况就不用讨论了。
对于拆分食物的问题,我们可以将食物总份数分为1,2,4…最后一个为总份数-(1+2+4+…)。
就像这样
for i:=1 to n do
begin
readln(t,u,vv);//t,u,vv对应题目中的t,u,v.
k:=1;
while vv>k do
begin
inc(v[0]);
v[v[0]]:=k*t;
w[v[0]]:=k*u;
vv:=vv-k;
k:=k*2;
end;
if vv>0 then//如还有剩余,则将剩余的也当成一块进行运输
begin
inc(v[0]);
v[v[0]]:=vv*t;
w[v[0]]:=vv*u;
end;
end;
Code
var v,w:array[0..2000] of longint;
x,y,z:array[0..200] of longint;
g:array[0..50101] of longint;
f:array[0..201,0..50101] of longint;
_,ans,a1,p,i,j,k,l,n,m,t,u,vv,mk:longint;
function max(a,b:longint):longint;
begin
if a>b then exit(a) else exit(b);
end;
function min(a,b:longint):longint;
begin
if a<b then exit(a) else exit(b);
end;
begin
readln(_);
while _>0 do
begin
dec(_);
fillchar(v,sizeof(v),0);
fillchar(w,sizeof(w),0);
fillchar(g,sizeof(g),127);
fillchar(f,sizeof(f),0);
a1:=maxlongint;
ans:=0;
readln(n,m,p);
mk:=p;
for i:=1 to n do
begin
readln(t,u,vv);
if t>mk then mk:=t;
k:=1;
while vv>k do
begin
inc(v[0]);
v[v[0]]:=k*t;
w[v[0]]:=k*u;
vv:=vv-k;
k:=k*2;
end;
if vv>0 then
begin
inc(v[0]);
v[v[0]]:=vv*t;
w[v[0]]:=vv*u;
end;
end;
for i:=1 to m do readln(x[i],y[i],z[i]);
g[0]:=0;
for i:=1 to v[0] do
for j:=mk+100 downto v[i] do
begin
g[j]:=min(g[j],g[j-v[i]]+w[i]);
if j>=p then a1:=min(a1,g[j]);
end;
if a1>=2139062143 then
begin//这时我们找不到a1,这说明无法获得p的美味度。
writeln('TAT');
continue;
end;
ans:=maxlongint;
for i:=1 to m do
for j:=0 to z[i] do
for k:=1 to 50000 do
if j*y[i]<=k then
begin
f[i,k]:=max(f[i,k],f[i-1,k-j*y[i]]+x[i]*j);
if f[i,k]>=a1 then
begin
ans:=min(ans,k);
break;
end;
end;
if ans>50000 then writeln('TAT') else writeln(ans);//这个就不用说了,当前最小费用已经大于50000.
end;
end.
——2016.2.16