HDU 5445 Food Problem(多重背包+二进制优化)
http://acm.hdu.edu.cn/showproblem.php?pid=5445
题意:
现在你要为运动会提供食物,总共需要提供P能量的食物,现在有n种食物,每种食物能提供 t 能量,体积为 u ,并且最多能提供 v 的数量。运载食物的卡车有m种,每种能提供 x 的运输空间,运输花费为 y,最多可以雇佣 z 辆车。食物可以切割后运输。不需要整块一起运输,但只有一整块全部到达时才能提供能量。
现在需要计算出最少需要多少花费。
思路:
因为食物可以切割运输,那么食物的总体积肯定是越小越好,所以先用多重背包计算出提供P能量所需的最少食物体积,食物的能量最多能提供100,所以背包容量到P+100即可。
有了体积之后,接下来只需要计算运输这些体积的食物最少需要多少花费,再用一次多重背包即可。
需要使用二进制优化。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 const int INF = 0x3f3f3f3f; 6 7 int n,m,p,tot; 8 int val[2005],cost[2005]; 9 int dp[50005]; 10 11 int solve1() 12 { 13 for(int i=0;i<=p+100;i++) dp[i] = INF; 14 dp[0] = 0; 15 for(int i=0;i<tot;i++) 16 for(int j=p+100;j>=val[i];j--) 17 dp[j] = min(dp[j],dp[j-val[i]]+cost[i]); 18 int ans = INF; 19 for(int i=p;i<=p+100;i++) 20 ans = min(ans, dp[i]); 21 return ans; 22 } 23 24 25 int solve2(int v) 26 { 27 memset(dp,0,sizeof dp); 28 for(int i=0;i<tot;i++) 29 for(int j=50000;j>=cost[i];j--) 30 dp[j] = max(dp[j],dp[j-cost[i]]+val[i]); 31 for(int i=1;i<=50000;i++) 32 if(dp[i]>=v) return i; 33 return INF; 34 } 35 36 int main() 37 { 38 //freopen("in.txt","r",stdin); 39 int T; 40 scanf("%d",&T); 41 while(T--) 42 { 43 scanf("%d%d%d",&n,&m,&p); 44 tot = 0; 45 for(int i=1;i<=n;i++) 46 { 47 int t,u,v; 48 scanf("%d%d%d",&t,&u,&v); 49 for(int k=1;v;k<<=1) 50 { 51 int num = min(k,v); 52 val[tot] = num*t; 53 cost[tot++] = num*u; 54 v -= num; 55 } 56 } 57 int v = solve1(); 58 tot = 0; 59 for(int i=1;i<=m;i++) 60 { 61 int x,y,z; 62 scanf("%d%d%d",&x,&y,&z); 63 for(int k=1;z;k<<=1) 64 { 65 int num = min(k,z); 66 cost[tot] = num*y; 67 val[tot++] = num*x; 68 z -= num; 69 } 70 } 71 if(v==INF) {puts("TAT");continue;} 72 int ans = solve2(v); 73 if(ans==INF) puts("TAT"); 74 else printf("%d\n",ans); 75 } 76 return 0; 77 }